From 586cd9fd435d684bd30a085688f96dd4c67dce35 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Mon, 14 Sep 2026 09:48:10 -0500 Subject: [PATCH 01/49] Initial prep work --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 35 +++++++++++++++++-- .../Runtime/Internal/Module.cs | 30 ++++++++++------ 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 5ecccedb31b..a11f139a3f9 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -32,10 +32,14 @@ private class Fixture(string projectDir, CSharpCompilation sampleCompilation) public CSharpParseOptions ParseOptions { get; } = (CSharpParseOptions)sampleCompilation.SyntaxTrees.First().Options; - public static async Task Compile(string name) + public static async Task Compile(string name, string? targetFramework = null) { var projectDir = Path.Combine(GetProjectDir(), "fixtures", name); - using var workspace = MSBuildWorkspace.Create(); + using var workspace = MSBuildWorkspace.Create( + targetFramework is null + ? [] + : new Dictionary { ["TargetFramework"] = targetFramework } + ); var sampleProject = await workspace.OpenProjectAsync($"{projectDir}/{name}.csproj"); var compilation = await sampleProject.GetCompilationAsync(); return new(projectDir, (CSharpCompilation)compilation!); @@ -173,7 +177,7 @@ static void AssertPublicBoundIsAvailableInRuntime(Compilation compilation) static void AssertRuntimeDoesNotDefineLocal(Compilation compilation) { var runtimeAssembly = compilation - .References.Select(r => compilation.GetAssemblyOrModuleSymbol(r)) + .References.Select(compilation.GetAssemblyOrModuleSymbol) .OfType() .FirstOrDefault(a => a.Name == "SpacetimeDB.Runtime"); @@ -206,6 +210,31 @@ static void AssertNoCs0436Diagnostics(Compilation compilation) Assert.DoesNotContain(diagnostics, d => d.Id == "CS0436"); } + [Fact] + // Make sure our existing C# module examples still compile when targeting .NET 8 (namespaces will only be supported on .NET 10) + public static async Task NamespaceProofPreservesNet8RootExamples() + { + foreach (var name in new[] { "server", "explicitnames" }) + { + var fixture = await Fixture.Compile(name, "net8.0"); + var compilation = fixture.SampleCompilation; + foreach ( + var generator in new IIncrementalGenerator[] + { + new SpacetimeDB.Codegen.Type(), + new SpacetimeDB.Codegen.Module(), + } + ) + { + compilation = compilation.AddSyntaxTrees( + fixture.RunGeneratorAndGetResult(generator).GeneratedTrees + ); + } + Assert.Empty(GetCompilationErrors(compilation)); + AssertRuntimeDoesNotDefineLocal(compilation); + } + } + [Fact] public static async Task TypeGeneratorOnClient() { diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index 438c3439146..14aa7f3afb2 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -10,6 +10,7 @@ namespace SpacetimeDB.Internal; partial class RawModuleDefV10 { private readonly Typespace typespace = new(); + private readonly List submoduleDefs = []; private readonly List typeDefs = []; private readonly List tableDefs = []; private readonly List scheduleDefs = []; @@ -37,11 +38,16 @@ private static string GetFriendlyName(Type type) => private static RawScopedTypeNameV10 MakeScopedTypeName(Type type) => new([], GetFriendlyName(type)); + + internal void RegisterSubmodule(RawSubmoduleV10 submodule) => + submoduleDefs.Add(submodule); - internal AlgebraicType.Ref RegisterType(Func makeType) + // Receives types to store the reference in the dictionary so that we can resolve it later and to avoid infinite recursion inside `makeType`. + internal AlgebraicType.Ref RegisterType(Dictionary types, Func makeType) { var typeList = typespace.Types; var typeRef = new AlgebraicType.Ref(typeList.Count); + types.Add(typeof(T), typeRef); // Put a dummy self-reference just so that we get stable index even if `makeType` recursively adds more types. typeList.Add(typeRef); typeList[typeRef.Ref_] = makeType(typeRef); @@ -169,6 +175,10 @@ internal RawModuleDefV10 BuildModuleDefinition() new RawModuleDefV10Section.Environment(environment), }; + if (submoduleDefs.Count > 0) + { + sections.Add(new RawModuleDefV10Section.Submodules([.. submoduleDefs])); + } if (typeDefs.Count > 0) { sections.Add(new RawModuleDefV10Section.Types(typeDefs)); @@ -335,9 +345,14 @@ public static void SetViewContextConstructor(Func ctor) public static void SetAnonymousViewContextConstructor(Func ctor) => newAnonymousViewContext = ctor; - public readonly struct TypeRegistrar() : ITypeRegistrar + public readonly struct TypeRegistrar : ITypeRegistrar { private readonly Dictionary types = []; + private readonly RawModuleDefV10 target; + + public TypeRegistrar() : this(moduleDef) { } + + internal TypeRegistrar(RawModuleDefV10 target) => this.target = target; // Registers type in the module definition. // @@ -349,18 +364,13 @@ public readonly struct TypeRegistrar() : ITypeRegistrar // e.g. self-recursion even before the algebraic type itself is constructed. public AlgebraicType.Ref RegisterType(Func makeType) { - // Store for the closure access. - var types = this.types; if (types.TryGetValue(typeof(T), out var existingTypeRef)) { return existingTypeRef; } - return moduleDef.RegisterType(typeRef => - { - // Store the type reference in the dictionary so that we can resolve it later and to avoid infinite recursion inside `makeType`. - types.Add(typeof(T), typeRef); - return makeType(typeRef); - }); + + // Passes types down to register the type reference in the dictionary so that we can resolve it later and to avoid infinite recursion inside `makeType`. + return target.RegisterType(types, makeType); } } From eee125cba2f23ff66a243b6753c44ed5bdc9bbb8 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Mon, 14 Sep 2026 12:27:35 -0500 Subject: [PATCH 02/49] Create ModuleBuilder that returns a RawModuleDef10 --- .../Runtime/Internal/Module.cs | 330 +--------------- .../Runtime/Internal/ModuleBuilder.cs | 352 ++++++++++++++++++ 2 files changed, 367 insertions(+), 315 deletions(-) create mode 100644 crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index 14aa7f3afb2..522117792b8 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -2,244 +2,10 @@ namespace SpacetimeDB.Internal; using System; using System.Collections.Generic; -using System.Linq; using System.Runtime.InteropServices; using SpacetimeDB; using SpacetimeDB.BSATN; -partial class RawModuleDefV10 -{ - private readonly Typespace typespace = new(); - private readonly List submoduleDefs = []; - private readonly List typeDefs = []; - private readonly List tableDefs = []; - private readonly List scheduleDefs = []; - private readonly List reducerDefs = []; - private readonly List lifecycleReducerDefs = []; - private readonly List procedureDefs = []; - private readonly List httpHandlerDefs = []; - private readonly List httpRouteDefs = []; - private readonly List viewDefs = []; - private readonly List viewPrimaryKeyDefs = []; - private readonly List environment = []; - private readonly List rowLevelSecurityDefs = []; - private readonly Dictionary> defaultValuesByTable = - new(StringComparer.Ordinal); - - private SpacetimeDB.CaseConversionPolicy? caseConversionPolicy = null; - private readonly List explicitNames = []; - - // Note: this intends to generate a valid identifier, but it's not guaranteed to be unique as it's not proper mangling. - // Fix it up to a different mangling scheme if it causes problems. - private static string GetFriendlyName(Type type) => - type.IsGenericType - ? $"{type.Name[..type.Name.IndexOf('`')]}_{string.Join("_", type.GetGenericArguments().Select(GetFriendlyName))}" - : type.Name; - - private static RawScopedTypeNameV10 MakeScopedTypeName(Type type) => - new([], GetFriendlyName(type)); - - internal void RegisterSubmodule(RawSubmoduleV10 submodule) => - submoduleDefs.Add(submodule); - - // Receives types to store the reference in the dictionary so that we can resolve it later and to avoid infinite recursion inside `makeType`. - internal AlgebraicType.Ref RegisterType(Dictionary types, Func makeType) - { - var typeList = typespace.Types; - var typeRef = new AlgebraicType.Ref(typeList.Count); - types.Add(typeof(T), typeRef); - // Put a dummy self-reference just so that we get stable index even if `makeType` recursively adds more types. - typeList.Add(typeRef); - typeList[typeRef.Ref_] = makeType(typeRef); - typeDefs.Add( - new RawTypeDefV10( - SourceName: MakeScopedTypeName(typeof(T)), - Ty: (uint)typeRef.Ref_, - CustomOrdering: true - ) - ); - return typeRef; - } - - internal void RegisterReducer(RawReducerDefV10 reducer, Lifecycle? lifecycle) - { - reducerDefs.Add(reducer); - if (lifecycle is { } lifecycleSpec) - { - lifecycleReducerDefs.Add( - new RawLifeCycleReducerDefV10(lifecycleSpec, reducer.SourceName) - ); - reducer.Visibility = FunctionVisibility.Private; - } - } - - internal void RegisterProcedure(RawProcedureDefV10 procedure) => procedureDefs.Add(procedure); - - internal void RegisterHttpHandler(RawHttpHandlerDefV10 handler) => httpHandlerDefs.Add(handler); - - internal bool HasHttpHandler(string sourceName) => - httpHandlerDefs.Any(handler => handler.SourceName == sourceName); - - internal void RegisterHttpRoute(RawHttpRouteDefV10 route) => httpRouteDefs.Add(route); - - internal void RegisterTable(RawTableDefV10 table, RawScheduleDefV10? schedule) - { - tableDefs.Add(table); - if (schedule is { } scheduleDef) - { - scheduleDefs.Add(scheduleDef); - } - } - - internal void RegisterView(RawViewDefV10 view) => viewDefs.Add(view); - - internal void RegisterEnvironment(EnvironmentDeclaration declaration) => - environment.Add(declaration); - - internal void RegisterViewPrimaryKey(string viewSourceName, IEnumerable columns) => - viewPrimaryKeyDefs.Add(new RawViewPrimaryKeyDefV10(viewSourceName, [.. columns])); - - internal void RegisterRowLevelSecurity(RawRowLevelSecurityDefV9 rls) => - rowLevelSecurityDefs.Add(rls); - - internal void RegisterTableDefaultValue(string table, ushort colId, byte[] value) - { - if (!defaultValuesByTable.TryGetValue(table, out var defaults)) - { - defaults = []; - defaultValuesByTable.Add(table, defaults); - } - defaults.Add(new RawColumnDefaultValueV10(colId, [.. value])); - } - - internal void SetCaseConversionPolicy(SpacetimeDB.CaseConversionPolicy policy) => - caseConversionPolicy = policy; - - internal void RegisterExplicitTableName(string sourceName, string canonicalName) => - explicitNames.Add(new ExplicitNameEntry.Table(new NameMapping(sourceName, canonicalName))); - - internal void RegisterExplicitFunctionName(string sourceName, string canonicalName) => - explicitNames.Add( - new ExplicitNameEntry.Function(new NameMapping(sourceName, canonicalName)) - ); - - internal void RegisterExplicitIndexName(string sourceName, string canonicalName) => - explicitNames.Add(new ExplicitNameEntry.Index(new NameMapping(sourceName, canonicalName))); - - internal RawModuleDefV10 BuildModuleDefinition() - { - var builtTables = new List(tableDefs.Count); - foreach (var table in tableDefs) - { - defaultValuesByTable.TryGetValue(table.SourceName, out var defaults); - builtTables.Add( - new RawTableDefV10( - SourceName: table.SourceName, - ProductTypeRef: table.ProductTypeRef, - PrimaryKey: table.PrimaryKey, - Indexes: table.Indexes, - Constraints: table.Constraints, - Sequences: table.Sequences, - TableType: table.TableType, - TableAccess: table.TableAccess, - DefaultValues: defaults is null ? [] : [.. defaults], - IsEvent: table.IsEvent - ) - ); - } - - var internalFunctions = lifecycleReducerDefs - .Select(l => l.FunctionName) - .Concat(scheduleDefs.Select(s => s.FunctionName)) - .ToHashSet(StringComparer.Ordinal); - - foreach (var reducer in reducerDefs) - { - if (internalFunctions.Contains(reducer.SourceName)) - { - reducer.Visibility = FunctionVisibility.Private; - } - } - - foreach (var procedure in procedureDefs) - { - if (internalFunctions.Contains(procedure.SourceName)) - { - procedure.Visibility = FunctionVisibility.Private; - } - } - - var sections = new List - { - new RawModuleDefV10Section.Typespace(typespace), - new RawModuleDefV10Section.Environment(environment), - }; - - if (submoduleDefs.Count > 0) - { - sections.Add(new RawModuleDefV10Section.Submodules([.. submoduleDefs])); - } - if (typeDefs.Count > 0) - { - sections.Add(new RawModuleDefV10Section.Types(typeDefs)); - } - if (builtTables.Count > 0) - { - sections.Add(new RawModuleDefV10Section.Tables(builtTables)); - } - if (reducerDefs.Count > 0) - { - sections.Add(new RawModuleDefV10Section.Reducers(reducerDefs)); - } - if (procedureDefs.Count > 0) - { - sections.Add(new RawModuleDefV10Section.Procedures(procedureDefs)); - } - if (httpHandlerDefs.Count > 0) - { - sections.Add(new RawModuleDefV10Section.HttpHandlers(httpHandlerDefs)); - } - if (httpRouteDefs.Count > 0) - { - sections.Add(new RawModuleDefV10Section.HttpRoutes(httpRouteDefs)); - } - if (viewDefs.Count > 0) - { - sections.Add(new RawModuleDefV10Section.Views(viewDefs)); - } - if (viewPrimaryKeyDefs.Count > 0) - { - sections.Add(new RawModuleDefV10Section.ViewPrimaryKeys(viewPrimaryKeyDefs)); - } - if (scheduleDefs.Count > 0) - { - sections.Add(new RawModuleDefV10Section.Schedules(scheduleDefs)); - } - if (lifecycleReducerDefs.Count > 0) - { - sections.Add(new RawModuleDefV10Section.LifeCycleReducers(lifecycleReducerDefs)); - } - // TODO: Add sections for Event tables and Case conversion policy (mirrors Rust `raw_def/v10.rs` TODO). - if (caseConversionPolicy is { } policy) - { - sections.Add(new RawModuleDefV10Section.CaseConversionPolicy(policy)); - } - if (explicitNames.Count > 0) - { - sections.Add( - new RawModuleDefV10Section.ExplicitNames(new ExplicitNames([.. explicitNames])) - ); - } - if (rowLevelSecurityDefs.Count > 0) - { - sections.Add(new RawModuleDefV10Section.RowLevelSecurity(rowLevelSecurityDefs)); - } - - Sections = sections; - return this; - } -} - public static class Module { // Workaround for NativeAOT-LLVM IL scanner bug: @@ -275,37 +41,7 @@ private static void EnsureNativeAotTypeRoots() } } - private static readonly RawModuleDefV10 moduleDef = new(); - - private static class ReducerCache - where R : IReducer, new() - { - public static readonly R Instance = new(); - } - - private static class ProcedureCache

- where P : IProcedure, new() - { - public static readonly P Instance = new(); - } - - private static class HttpHandlerCache - where H : IHttpHandler, new() - { - public static readonly H Instance = new(); - } - - private static class ViewDispatcherCache - where TDispatcher : IView, new() - { - public static readonly TDispatcher Instance = new(); - } - - private static class AnonymousViewDispatcherCache - where TDispatcher : IAnonymousView, new() - { - public static readonly TDispatcher Instance = new(); - } + private static readonly ModuleBuilder moduleDef = new(); private static Func< Identity, @@ -348,11 +84,12 @@ public static void SetAnonymousViewContextConstructor(Func types = []; - private readonly RawModuleDefV10 target; + private readonly ModuleBuilder target; - public TypeRegistrar() : this(moduleDef) { } + public TypeRegistrar() + : this(moduleDef) { } - internal TypeRegistrar(RawModuleDefV10 target) => this.target = target; + internal TypeRegistrar(ModuleBuilder target) => this.target = target; // Registers type in the module definition. // @@ -374,72 +111,44 @@ public AlgebraicType.Ref RegisterType(Func } } - static readonly TypeRegistrar typeRegistrar = new(); - public static void RegisterReducer() where R : IReducer, new() { - var reducer = ReducerCache.Instance; - moduleDef.RegisterReducer(reducer.MakeReducerDef(typeRegistrar), reducer.Lifecycle); + moduleDef.RegisterReducer(); } public static void RegisterProcedure

() where P : IProcedure, new() { - var procedure = ProcedureCache

.Instance; - moduleDef.RegisterProcedure(procedure.MakeProcedureDef(typeRegistrar)); + moduleDef.RegisterProcedure

(); } public static void RegisterHttpHandler() where H : IHttpHandler, new() { - var handler = HttpHandlerCache.Instance; - moduleDef.RegisterHttpHandler(handler.MakeHandlerDef()); + moduleDef.RegisterHttpHandler(); } - public static void RegisterHttpRouter(SpacetimeDB.Router router) - { - foreach (var route in router.GetRoutes()) - { - if (!moduleDef.HasHttpHandler(route.HandlerFunction)) - { - throw new ArgumentException( - $"HTTP router references unknown handler `{route.HandlerFunction}`", - nameof(router) - ); - } - - moduleDef.RegisterHttpRoute( - new RawHttpRouteDefV10( - HandlerFunction: route.HandlerFunction, - Method: route.Method, - Path: route.Path - ) - ); - } - } + public static void RegisterHttpRouter(SpacetimeDB.Router router) => + moduleDef.RegisterHttpRouter(router); public static void RegisterTable() where T : IStructuralReadWrite, new() where View : ITableView, new() { - moduleDef.RegisterTable(View.MakeTableDesc(typeRegistrar), View.MakeScheduleDesc()); + moduleDef.RegisterTable(); } public static void RegisterView() where TDispatcher : IView, new() { - var dispatcher = ViewDispatcherCache.Instance; - var def = dispatcher.MakeViewDef(typeRegistrar); - moduleDef.RegisterView(def); + moduleDef.RegisterView(); } public static void RegisterAnonymousView() where TDispatcher : IAnonymousView, new() { - var dispatcher = AnonymousViewDispatcherCache.Instance; - var def = dispatcher.MakeAnonymousViewDef(typeRegistrar); - moduleDef.RegisterView(def); + moduleDef.RegisterAnonymousView(); } public static void RegisterEnvironment(EnvironmentDeclaration declaration) => @@ -448,17 +157,8 @@ public static void RegisterEnvironment(EnvironmentDeclaration declaration) => public static void RegisterViewPrimaryKey(string viewSourceName, string[] columns) => moduleDef.RegisterViewPrimaryKey(viewSourceName, columns); - public static void RegisterClientVisibilityFilter(Filter rlsFilter) - { - if (rlsFilter is Filter.Sql(var rlsSql)) - { - moduleDef.RegisterRowLevelSecurity(new RawRowLevelSecurityDefV9 { Sql = rlsSql }); - } - else - { - throw new Exception($"Unimplemented row level security type: {rlsFilter}"); - } - } + public static void RegisterClientVisibilityFilter(Filter rlsFilter) => + moduleDef.RegisterClientVisibilityFilter(rlsFilter); public static void RegisterTableDefaultValue(string table, ushort colId, byte[] value) => moduleDef.RegisterTableDefaultValue(table, colId, value); diff --git a/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs b/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs new file mode 100644 index 00000000000..2548d6ce6b6 --- /dev/null +++ b/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs @@ -0,0 +1,352 @@ +namespace SpacetimeDB.Internal; + +using System; +using System.Collections.Generic; +using System.Linq; +using SpacetimeDB.BSATN; + +internal sealed class ModuleBuilder +{ + internal Module.TypeRegistrar TypeRegistrar { get; } + + internal ModuleBuilder() => TypeRegistrar = new Module.TypeRegistrar(this); + + private static class ReducerCache + where R : IReducer, new() + { + public static readonly R Instance = new(); + } + + private static class ProcedureCache

+ where P : IProcedure, new() + { + public static readonly P Instance = new(); + } + + private static class HttpHandlerCache + where H : IHttpHandler, new() + { + public static readonly H Instance = new(); + } + + private static class ViewDispatcherCache + where TDispatcher : IView, new() + { + public static readonly TDispatcher Instance = new(); + } + + private static class AnonymousViewDispatcherCache + where TDispatcher : IAnonymousView, new() + { + public static readonly TDispatcher Instance = new(); + } + + private readonly Typespace typespace = new(); + private readonly List submoduleDefs = []; + private readonly List typeDefs = []; + private readonly List tableDefs = []; + private readonly List scheduleDefs = []; + private readonly List reducerDefs = []; + private readonly List lifecycleReducerDefs = []; + private readonly List procedureDefs = []; + private readonly List httpHandlerDefs = []; + private readonly List httpRouteDefs = []; + private readonly List viewDefs = []; + private readonly List viewPrimaryKeyDefs = []; + private readonly List environment = []; + private readonly List rowLevelSecurityDefs = []; + private readonly Dictionary> defaultValuesByTable = + new(StringComparer.Ordinal); + + private SpacetimeDB.CaseConversionPolicy? caseConversionPolicy = null; + private readonly List explicitNames = []; + + // Note: this intends to generate a valid identifier, but it's not guaranteed to be unique as it's not proper mangling. + // Fix it up to a different mangling scheme if it causes problems. + private static string GetFriendlyName(Type type) => + type.IsGenericType + ? $"{type.Name[..type.Name.IndexOf('`')]}_{string.Join("_", type.GetGenericArguments().Select(GetFriendlyName))}" + : type.Name; + + private static RawScopedTypeNameV10 MakeScopedTypeName(Type type) => + new([], GetFriendlyName(type)); + + internal void RegisterSubmodule(RawSubmoduleV10 submodule) => submoduleDefs.Add(submodule); + + // Receives types to store the reference in the dictionary so that we can resolve it later and to avoid infinite recursion inside `makeType`. + internal AlgebraicType.Ref RegisterType( + Dictionary types, + Func makeType + ) + { + var typeList = typespace.Types; + var typeRef = new AlgebraicType.Ref(typeList.Count); + types.Add(typeof(T), typeRef); + // Put a dummy self-reference just so that we get stable index even if `makeType` recursively adds more types. + typeList.Add(typeRef); + typeList[typeRef.Ref_] = makeType(typeRef); + typeDefs.Add( + new RawTypeDefV10( + SourceName: MakeScopedTypeName(typeof(T)), + Ty: (uint)typeRef.Ref_, + CustomOrdering: true + ) + ); + return typeRef; + } + + internal void RegisterReducer() + where R : IReducer, new() + { + var reducer = ReducerCache.Instance; + RegisterReducer(reducer.MakeReducerDef(TypeRegistrar), reducer.Lifecycle); + } + + internal void RegisterReducer(RawReducerDefV10 reducer, Lifecycle? lifecycle) + { + reducerDefs.Add(reducer); + if (lifecycle is { } lifecycleSpec) + { + lifecycleReducerDefs.Add( + new RawLifeCycleReducerDefV10(lifecycleSpec, reducer.SourceName) + ); + reducer.Visibility = FunctionVisibility.Private; + } + } + + internal void RegisterProcedure

() + where P : IProcedure, new() + { + var procedure = ProcedureCache

.Instance; + RegisterProcedure(procedure.MakeProcedureDef(TypeRegistrar)); + } + + internal void RegisterProcedure(RawProcedureDefV10 procedure) => procedureDefs.Add(procedure); + + internal void RegisterHttpHandler() + where H : IHttpHandler, new() + { + var handler = HttpHandlerCache.Instance; + RegisterHttpHandler(handler.MakeHandlerDef()); + } + + internal void RegisterHttpHandler(RawHttpHandlerDefV10 handler) => httpHandlerDefs.Add(handler); + + internal void RegisterHttpRouter(SpacetimeDB.Router router) + { + foreach (var route in router.GetRoutes()) + { + if (!HasHttpHandler(route.HandlerFunction)) + { + throw new ArgumentException( + $"HTTP router references unknown handler `{route.HandlerFunction}`", + nameof(router) + ); + } + + RegisterHttpRoute( + new RawHttpRouteDefV10( + HandlerFunction: route.HandlerFunction, + Method: route.Method, + Path: route.Path + ) + ); + } + } + + internal bool HasHttpHandler(string sourceName) => + httpHandlerDefs.Any(handler => handler.SourceName == sourceName); + + internal void RegisterHttpRoute(RawHttpRouteDefV10 route) => httpRouteDefs.Add(route); + + internal void RegisterTable() + where T : IStructuralReadWrite, new() + where View : ITableView, new() + { + RegisterTable(View.MakeTableDesc(TypeRegistrar), View.MakeScheduleDesc()); + } + + internal void RegisterTable(RawTableDefV10 table, RawScheduleDefV10? schedule) + { + tableDefs.Add(table); + if (schedule is { } scheduleDef) + { + scheduleDefs.Add(scheduleDef); + } + } + + internal void RegisterView() + where TDispatcher : IView, new() + { + var dispatcher = ViewDispatcherCache.Instance; + var def = dispatcher.MakeViewDef(TypeRegistrar); + RegisterView(def); + } + + internal void RegisterAnonymousView() + where TDispatcher : IAnonymousView, new() + { + var dispatcher = AnonymousViewDispatcherCache.Instance; + var def = dispatcher.MakeAnonymousViewDef(TypeRegistrar); + RegisterView(def); + } + + internal void RegisterView(RawViewDefV10 view) => viewDefs.Add(view); + + internal void RegisterEnvironment(EnvironmentDeclaration declaration) => + environment.Add(declaration); + + internal void RegisterViewPrimaryKey(string viewSourceName, IEnumerable columns) => + viewPrimaryKeyDefs.Add(new RawViewPrimaryKeyDefV10(viewSourceName, [.. columns])); + + internal void RegisterClientVisibilityFilter(Filter rlsFilter) + { + if (rlsFilter is Filter.Sql(var rlsSql)) + { + RegisterRowLevelSecurity(new RawRowLevelSecurityDefV9 { Sql = rlsSql }); + } + else + { + throw new Exception($"Unimplemented row level security type: {rlsFilter}"); + } + } + + internal void RegisterRowLevelSecurity(RawRowLevelSecurityDefV9 rls) => + rowLevelSecurityDefs.Add(rls); + + internal void RegisterTableDefaultValue(string table, ushort colId, byte[] value) + { + if (!defaultValuesByTable.TryGetValue(table, out var defaults)) + { + defaults = []; + defaultValuesByTable.Add(table, defaults); + } + defaults.Add(new RawColumnDefaultValueV10(colId, [.. value])); + } + + internal void SetCaseConversionPolicy(SpacetimeDB.CaseConversionPolicy policy) => + caseConversionPolicy = policy; + + internal void RegisterExplicitTableName(string sourceName, string canonicalName) => + explicitNames.Add(new ExplicitNameEntry.Table(new NameMapping(sourceName, canonicalName))); + + internal void RegisterExplicitFunctionName(string sourceName, string canonicalName) => + explicitNames.Add( + new ExplicitNameEntry.Function(new NameMapping(sourceName, canonicalName)) + ); + + internal void RegisterExplicitIndexName(string sourceName, string canonicalName) => + explicitNames.Add(new ExplicitNameEntry.Index(new NameMapping(sourceName, canonicalName))); + + internal RawModuleDefV10 BuildModuleDefinition() + { + var builtTables = new List(tableDefs.Count); + foreach (var table in tableDefs) + { + defaultValuesByTable.TryGetValue(table.SourceName, out var defaults); + builtTables.Add( + new RawTableDefV10( + SourceName: table.SourceName, + ProductTypeRef: table.ProductTypeRef, + PrimaryKey: table.PrimaryKey, + Indexes: table.Indexes, + Constraints: table.Constraints, + Sequences: table.Sequences, + TableType: table.TableType, + TableAccess: table.TableAccess, + DefaultValues: defaults is null ? [] : [.. defaults], + IsEvent: table.IsEvent + ) + ); + } + + var internalFunctions = lifecycleReducerDefs + .Select(l => l.FunctionName) + .Concat(scheduleDefs.Select(s => s.FunctionName)) + .ToHashSet(StringComparer.Ordinal); + + foreach (var reducer in reducerDefs) + { + if (internalFunctions.Contains(reducer.SourceName)) + { + reducer.Visibility = FunctionVisibility.Private; + } + } + + foreach (var procedure in procedureDefs) + { + if (internalFunctions.Contains(procedure.SourceName)) + { + procedure.Visibility = FunctionVisibility.Private; + } + } + + var sections = new List + { + new RawModuleDefV10Section.Typespace(typespace), + new RawModuleDefV10Section.Environment(environment), + }; + + if (submoduleDefs.Count > 0) + { + sections.Add(new RawModuleDefV10Section.Submodules([.. submoduleDefs])); + } + if (typeDefs.Count > 0) + { + sections.Add(new RawModuleDefV10Section.Types(typeDefs)); + } + if (builtTables.Count > 0) + { + sections.Add(new RawModuleDefV10Section.Tables(builtTables)); + } + if (reducerDefs.Count > 0) + { + sections.Add(new RawModuleDefV10Section.Reducers(reducerDefs)); + } + if (procedureDefs.Count > 0) + { + sections.Add(new RawModuleDefV10Section.Procedures(procedureDefs)); + } + if (httpHandlerDefs.Count > 0) + { + sections.Add(new RawModuleDefV10Section.HttpHandlers(httpHandlerDefs)); + } + if (httpRouteDefs.Count > 0) + { + sections.Add(new RawModuleDefV10Section.HttpRoutes(httpRouteDefs)); + } + if (viewDefs.Count > 0) + { + sections.Add(new RawModuleDefV10Section.Views(viewDefs)); + } + if (viewPrimaryKeyDefs.Count > 0) + { + sections.Add(new RawModuleDefV10Section.ViewPrimaryKeys(viewPrimaryKeyDefs)); + } + if (scheduleDefs.Count > 0) + { + sections.Add(new RawModuleDefV10Section.Schedules(scheduleDefs)); + } + if (lifecycleReducerDefs.Count > 0) + { + sections.Add(new RawModuleDefV10Section.LifeCycleReducers(lifecycleReducerDefs)); + } + // TODO: Add sections for Event tables and Case conversion policy (mirrors Rust `raw_def/v10.rs` TODO). + if (caseConversionPolicy is { } policy) + { + sections.Add(new RawModuleDefV10Section.CaseConversionPolicy(policy)); + } + if (explicitNames.Count > 0) + { + sections.Add( + new RawModuleDefV10Section.ExplicitNames(new ExplicitNames([.. explicitNames])) + ); + } + if (rowLevelSecurityDefs.Count > 0) + { + sections.Add(new RawModuleDefV10Section.RowLevelSecurity(rowLevelSecurityDefs)); + } + + return new RawModuleDefV10(sections); + } +} From 8bf4267b29f360b31afa11f0a7c933fafcb2d5aa Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Mon, 14 Sep 2026 14:50:15 -0500 Subject: [PATCH 03/49] Move Local and RuntimeContext to Runtime in .NET 10 --- .../bindings-csharp/Codegen.Tests/TestInit.cs | 8 ++ crates/bindings-csharp/Codegen.Tests/Tests.cs | 61 ++++++++++++--- crates/bindings-csharp/Codegen/Module.cs | 37 ++++++++- .../Runtime/Internal/Module.cs | 8 +- .../bindings-csharp/Runtime/ModuleContexts.cs | 76 +++++++++++++++++++ 5 files changed, 174 insertions(+), 16 deletions(-) create mode 100644 crates/bindings-csharp/Runtime/ModuleContexts.cs diff --git a/crates/bindings-csharp/Codegen.Tests/TestInit.cs b/crates/bindings-csharp/Codegen.Tests/TestInit.cs index 17b229a8d75..9ceb6a3cfa8 100644 --- a/crates/bindings-csharp/Codegen.Tests/TestInit.cs +++ b/crates/bindings-csharp/Codegen.Tests/TestInit.cs @@ -72,6 +72,14 @@ public static void Initialize() (sb) => { var unformattedCode = sb.ToString(); + // CSharpier 0.28 cannot preserve C# 14 extension declarations, even in inactive branches. + // Only trim trailing whitespace; generator tests compile the original syntax trees. + if (unformattedCode.Contains("extension(global::SpacetimeDB.Local db)")) + { + sb.Clear(); + sb.Append(string.Join("\n", unformattedCode.Split('\n').Select(line => line.TrimEnd()))); + return; + } sb.Clear(); var result = CSharpier.CodeFormatter.Format( unformattedCode, diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index a11f139a3f9..c04c153ff41 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -20,6 +20,12 @@ namespace SpacetimeDB.Codegen.Tests; /// public static class GeneratorSnapshotTests { +#if NET10_0_OR_GREATER + private const string ModuleTargetFramework = "net10.0"; +#else + private const string ModuleTargetFramework = "net8.0"; +#endif + // Note that we can't use assembly path here because it will be put in some deep nested folder. // Instead, to get the test project directory, we can use the `CallerFilePath` attribute which will magically give us path to the current file. static string GetProjectDir([CallerFilePath] string path = "") => Path.GetDirectoryName(path)!; @@ -34,19 +40,24 @@ private class Fixture(string projectDir, CSharpCompilation sampleCompilation) public static async Task Compile(string name, string? targetFramework = null) { + targetFramework ??= name == "client" ? "netstandard2.1" : ModuleTargetFramework; var projectDir = Path.Combine(GetProjectDir(), "fixtures", name); using var workspace = MSBuildWorkspace.Create( - targetFramework is null - ? [] - : new Dictionary { ["TargetFramework"] = targetFramework } + new Dictionary { ["TargetFramework"] = targetFramework } ); var sampleProject = await workspace.OpenProjectAsync($"{projectDir}/{name}.csproj"); var compilation = await sampleProject.GetCompilationAsync(); return new(projectDir, (CSharpCompilation)compilation!); } - public Task Verify(string fileName, object target) => - Verifier.Verify(target).UseDirectory($"{projectDir}/snapshots").UseFileName(fileName); + public Task Verify(string fileName, object target) + { + if (fileName == nameof(Module) && ModuleTargetFramework == "net10.0") + { + fileName += ".net10"; + } + return Verifier.Verify(target).UseDirectory($"{projectDir}/snapshots").UseFileName(fileName); + } private static CSharpGeneratorDriver CreateDriver( IIncrementalGenerator generator, @@ -174,7 +185,7 @@ static void AssertPublicBoundIsAvailableInRuntime(Compilation compilation) Assert.Equal(Accessibility.Public, bound!.DeclaredAccessibility); } - static void AssertRuntimeDoesNotDefineLocal(Compilation compilation) + static void AssertContextOwnership(Compilation compilation) { var runtimeAssembly = compilation .References.Select(compilation.GetAssemblyOrModuleSymbol) @@ -183,14 +194,39 @@ static void AssertRuntimeDoesNotDefineLocal(Compilation compilation) Assert.NotNull(runtimeAssembly); + // Use the fixture's target, not the test host: the .NET 10 suite also compiles .NET 8 examples. + var sharedContexts = ((CSharpParseOptions)compilation.SyntaxTrees.First().Options) + .PreprocessorSymbolNames.Contains("NET10_0_OR_GREATER"); + foreach (var name in new[] { "SpacetimeDB.Local", "SpacetimeDB.ReducerContext" }) + { + var runtimeType = runtimeAssembly!.GetTypeByMetadataName(name); + var generatedType = compilation.Assembly.GetTypeByMetadataName(name); + if (sharedContexts) + { + Assert.NotNull(runtimeType); + Assert.Equal(Accessibility.Public, runtimeType!.DeclaredAccessibility); + Assert.Null(generatedType); + } + else + { + Assert.Null(runtimeType); + Assert.NotNull(generatedType); + } + Assert.True( + SymbolEqualityComparer.Default.Equals( + sharedContexts ? runtimeType : generatedType, + compilation.GetTypeByMetadataName(name) + ), + $"{name} must resolve to its owning assembly without ambiguity." + ); + } + // These types are generated per-module by SpacetimeDB.Codegen.Module. // If Runtime defines any of them too, user projects can hit CS0436 warnings. var codegenOwnedTypes = new[] { - "SpacetimeDB.Local", "SpacetimeDB.ProcedureContext", "SpacetimeDB.ProcedureTxContext", - "SpacetimeDB.ReducerContext", "SpacetimeDB.ViewContext", "SpacetimeDB.AnonymousViewContext", }; @@ -198,6 +234,7 @@ static void AssertRuntimeDoesNotDefineLocal(Compilation compilation) foreach (var name in codegenOwnedTypes) { Assert.Null(runtimeAssembly!.GetTypeByMetadataName(name)); + Assert.NotNull(compilation.Assembly.GetTypeByMetadataName(name)); } } @@ -231,7 +268,7 @@ public static async Task NamespaceProofPreservesNet8RootExamples() ); } Assert.Empty(GetCompilationErrors(compilation)); - AssertRuntimeDoesNotDefineLocal(compilation); + AssertContextOwnership(compilation); } } @@ -260,7 +297,7 @@ public static async Task TypeAndModuleGeneratorsOnServer() Assert.Empty(GetCompilationErrors(compilationAfterGen)); AssertPublicBoundIsAvailableInRuntime(compilationAfterGen); - AssertRuntimeDoesNotDefineLocal(compilationAfterGen); + AssertContextOwnership(compilationAfterGen); AssertGeneratedCodeDoesNotUseInternalBound(compilationAfterGen); // Regression guard for user-reported warning spam: @@ -285,7 +322,7 @@ public static async Task SettingsAndExplicitNames() Assert.Empty(GetCompilationErrors(compilationAfterGen)); AssertPublicBoundIsAvailableInRuntime(compilationAfterGen); - AssertRuntimeDoesNotDefineLocal(compilationAfterGen); + AssertContextOwnership(compilationAfterGen); AssertGeneratedCodeDoesNotUseInternalBound(compilationAfterGen); } @@ -397,7 +434,7 @@ public static async Task TestDiagnostics() await fixture.Verify("ExtraCompilationErrors", GetCompilationErrors(compilationAfterGen)); AssertPublicBoundIsAvailableInRuntime(compilationAfterGen); - AssertRuntimeDoesNotDefineLocal(compilationAfterGen); + AssertContextOwnership(compilationAfterGen); AssertGeneratedCodeDoesNotUseInternalBound(compilationAfterGen); } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 29fc16d2cfc..0baec31b011 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -2407,12 +2407,23 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Combine(columnDefaultValues) .Select((tuple, ct) => FlattenModuleOutputInputs(tuple)); + var extensionNamespace = context.CompilationProvider.Select( + (compilation, _) => + "SpacetimeDB.Generated.Assembly_" + + string.Concat( + compilation.Assembly.Identity.ToString() + .Select(c => ((int)c).ToString("X4")) + ) + ); + // Register the generated source code with the compilation context as part of module publishing // Once the compilation is complete, the generated code will be used to create tables and reducers in the database context.RegisterSourceOutput( - moduleOutputInputs, - (context, inputs) => + moduleOutputInputs.Combine(extensionNamespace), + (context, input) => { + var (inputs, extensionNamespaceName) = input; + var ( tableAccessors, settings, @@ -2543,6 +2554,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context) #pragma warning disable CS0436 #pragma warning disable STDB_UNSTABLE + #if NET10_0_OR_GREATER + global using {{extensionNamespaceName}}; + #endif using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -2556,6 +2570,8 @@ public static class Handlers { $"public static readonly global::SpacetimeDB.Handler {EscapeIdentifier(r.Name)} = new(nameof({r.FullName}));" ))}} } + + #if !NET10_0_OR_GREATER public sealed record ReducerContext : DbContext, Internal.IReducerContext { public global::SpacetimeDB.ModuleEnvironment Env => default; public readonly Identity Sender; @@ -2627,7 +2643,8 @@ public Uuid NewUuidV7() return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); } } - + #endif + public sealed partial class ProcedureContext : global::SpacetimeDB.ProcedureContextBase { public new global::SpacetimeDB.ModuleEnvironment Env => default; private readonly Local _db = new(); @@ -2752,9 +2769,11 @@ internal HandlerTxContext(Internal.TxContext inner) : base(inner) {} public new Local Db => (Local)base.Db; } + #if !NET10_0_OR_GREATER public sealed class Local : global::SpacetimeDB.LocalBase { {{string.Join("\n", tableAccessors.Select(v => v.Getter))}} } + #endif public sealed record ViewContext : DbContext, Internal.IViewContext { @@ -2780,6 +2799,16 @@ internal AnonymousViewContext(Internal.LocalReadOnly db) } } + #if NET10_0_OR_GREATER + namespace {{extensionNamespaceName}} { + public static class LocalTableExtensions { + extension(global::SpacetimeDB.Local db) { + {{string.Join("\n", tableAccessors.Select(v => v.Getter))}} + } + } + } + #endif + namespace SpacetimeDB.Internal.TableHandles { {{string.Join("\n", tableAccessors.Select(v => v.TableAccessor))}} } @@ -2834,7 +2863,9 @@ public static List ToListOrEmpty(T? value) where T : class [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, typeof(ModuleRegistration))] #endif public static void Main() { + #if !NET10_0_OR_GREATER SpacetimeDB.Internal.Module.SetReducerContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ReducerContext(identity, connectionId, random, time)); + #endif SpacetimeDB.Internal.Module.SetViewContextConstructor(identity => new SpacetimeDB.ViewContext(identity, new SpacetimeDB.Internal.LocalReadOnly())); SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor(() => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly())); SpacetimeDB.Internal.Module.SetProcedureContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ProcedureContext(identity, connectionId, random, time));{{preRegistrations}} diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index 522117792b8..47b6b908466 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -49,7 +49,13 @@ private static Func< Random, Timestamp, IReducerContext - >? newReducerContext = null; + >? newReducerContext = +#if NET10_0_OR_GREATER + (identity, connectionId, random, time) => + new SpacetimeDB.ReducerContext(identity, connectionId, random, time); +#else + null; +#endif private static Func? newViewContext = null; private static Func? newAnonymousViewContext = null; private static Func? newHandlerContext = diff --git a/crates/bindings-csharp/Runtime/ModuleContexts.cs b/crates/bindings-csharp/Runtime/ModuleContexts.cs new file mode 100644 index 00000000000..2586cf711a4 --- /dev/null +++ b/crates/bindings-csharp/Runtime/ModuleContexts.cs @@ -0,0 +1,76 @@ +#if NET10_0_OR_GREATER +namespace SpacetimeDB; + +public sealed class Local : LocalBase { } + +public sealed record ReducerContext : DbContext, Internal.IReducerContext { + public readonly Identity Sender; + public readonly ConnectionId? ConnectionId; + public readonly Random Rng; + public readonly Timestamp Timestamp; + public readonly AuthCtx SenderAuth; + // **Note:** must be 0..=u32::MAX + internal int CounterUuid; + public Identity DatabaseIdentity => Internal.IReducerContext.GetDatabaseIdentity(); + // We keep this property for compatibility with existing module code. + [global::System.Obsolete("ReducerContext.Identity is deprecated. Use DatabaseIdentity instead.")] + public Identity Identity => DatabaseIdentity; + + internal ReducerContext(Identity identity, ConnectionId? connectionId, Random random, + Timestamp time, AuthCtx? senderAuth = null) + { + Sender = identity; + ConnectionId = connectionId; + Rng = random; + Timestamp = time; + SenderAuth = senderAuth ?? AuthCtx.BuildFromSystemTables(connectionId, identity); + CounterUuid = 0; + } + ///

+ /// Create a new random `v4` using the built-in RNG. + /// + /// + /// This method fills the random bytes using the context RNG. + /// + /// + /// + /// var uuid = ctx.NewUuidV4(); + /// Log.Info(uuid); + /// + /// + public Uuid NewUuidV4() + { + var bytes = new byte[16]; + Rng.NextBytes(bytes); + return Uuid.FromRandomBytesV4(bytes); + } + + /// + /// Create a new sortable `v7` using the built-in RNG, monotonic counter, + /// and timestamp. + /// + /// + /// A newly generated `v7` that is monotonically ordered + /// and suitable for use as a primary key or for ordered storage. + /// + /// + /// Thrown if generation fails. + /// + /// + /// + /// [SpacetimeDB.Reducer] + /// public static Guid GenerateUuidV7(ReducerContext ctx) + /// { + /// Guid uuid = ctx.NewUuidV7(); + /// Log.Info(uuid); + /// } + /// + /// + public Uuid NewUuidV7() + { + var bytes = new byte[4]; + Rng.NextBytes(bytes); + return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); + } +} +#endif \ No newline at end of file From f76db94ef217a3fd6b75f569728ef55d055c4ec1 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Tue, 15 Sep 2026 10:01:07 -0500 Subject: [PATCH 04/49] Move procedures, handlers, views and query builder to Runtime in .NET 10 --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 104 ++++++++++-- crates/bindings-csharp/Codegen/Module.cs | 39 +++-- .../Runtime/Internal/Module.cs | 33 +++- .../bindings-csharp/Runtime/ModuleContexts.cs | 151 +++++++++++++++++- 4 files changed, 290 insertions(+), 37 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index c04c153ff41..07e8b5f70e2 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -52,7 +52,8 @@ public static async Task Compile(string name, string? targetFramework = public Task Verify(string fileName, object target) { - if (fileName == nameof(Module) && ModuleTargetFramework == "net10.0") + if ((fileName == nameof(Module) || fileName == "ExtraCompilationErrors") + && ModuleTargetFramework == "net10.0") { fileName += ".net10"; } @@ -197,7 +198,18 @@ static void AssertContextOwnership(Compilation compilation) // Use the fixture's target, not the test host: the .NET 10 suite also compiles .NET 8 examples. var sharedContexts = ((CSharpParseOptions)compilation.SyntaxTrees.First().Options) .PreprocessorSymbolNames.Contains("NET10_0_OR_GREATER"); - foreach (var name in new[] { "SpacetimeDB.Local", "SpacetimeDB.ReducerContext" }) + foreach (var name in new[] + { + "SpacetimeDB.Local", + "SpacetimeDB.ReducerContext", + "SpacetimeDB.ProcedureContext", + "SpacetimeDB.ProcedureTxContext", + "SpacetimeDB.HandlerContext", + "SpacetimeDB.HandlerTxContext", + "SpacetimeDB.ViewContext", + "SpacetimeDB.AnonymousViewContext", + "SpacetimeDB.QueryBuilder", + }) { var runtimeType = runtimeAssembly!.GetTypeByMetadataName(name); var generatedType = compilation.Assembly.GetTypeByMetadataName(name); @@ -221,20 +233,16 @@ static void AssertContextOwnership(Compilation compilation) ); } - // These types are generated per-module by SpacetimeDB.Codegen.Module. - // If Runtime defines any of them too, user projects can hit CS0436 warnings. - var codegenOwnedTypes = new[] + // The legacy runtime shell remains on .NET 8, where generated code shadows it. + var readOnlyName = "SpacetimeDB.Internal.LocalReadOnly"; + Assert.NotNull(runtimeAssembly!.GetTypeByMetadataName(readOnlyName)); + if (sharedContexts) { - "SpacetimeDB.ProcedureContext", - "SpacetimeDB.ProcedureTxContext", - "SpacetimeDB.ViewContext", - "SpacetimeDB.AnonymousViewContext", - }; - - foreach (var name in codegenOwnedTypes) + Assert.Null(compilation.Assembly.GetTypeByMetadataName(readOnlyName)); + } + else { - Assert.Null(runtimeAssembly!.GetTypeByMetadataName(name)); - Assert.NotNull(compilation.Assembly.GetTypeByMetadataName(name)); + Assert.NotNull(compilation.Assembly.GetTypeByMetadataName(readOnlyName)); } } @@ -284,6 +292,74 @@ public static async Task TypeGeneratorOnClient() Assert.Empty(GetCompilationErrors(compilationAfterGen)); } +#if NET10_0_OR_GREATER + [Fact] + // Can a separately compiled DLL accept our module’s contexts, and can module code still access tables through the contexts it returns? + public static async Task NamespaceContextsCrossAssemblyBoundaries() + { + var fixture = await Fixture.Compile("server"); + var contextNames = new[] + { + "ReducerContext", "ProcedureContext", "ProcedureTxContext", + "HandlerContext", "HandlerTxContext", "ViewContext", "AnonymousViewContext", + }; + var helperSource = "#pragma warning disable STDB_UNSTABLE\npublic static class ContextHelpers {" + + string.Join("\n", contextNames.Select(name => + $"public static SpacetimeDB.{name} Pass(SpacetimeDB.{name} ctx) => ctx;")) + + "}"; + var helper = CSharpCompilation.Create( + "ContextHelperLibrary", + [CSharpSyntaxTree.ParseText(helperSource, fixture.ParseOptions)], + fixture.SampleCompilation.References, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) + ); + using var dll = new MemoryStream(); + var emitted = helper.Emit(dll); + Assert.True(emitted.Success, string.Join("\n", emitted.Diagnostics)); + + var compilation = fixture.SampleCompilation.AddReferences( + MetadataReference.CreateFromImage(dll.ToArray()) + ); + foreach (var generator in new IIncrementalGenerator[] { new Type(), new Module() }) + { + compilation = compilation.AddSyntaxTrees( + fixture.RunGeneratorAndGetResult(generator).GeneratedTrees + ); + } + var consumer = "#pragma warning disable STDB_UNSTABLE\n" + """ + public static class ContextConsumer + { + public static void Write(SpacetimeDB.ProcedureTxContext ctx) => + ContextHelpers.Pass(ctx).Db.PublicTable.Insert(default); + public static void Write(SpacetimeDB.HandlerTxContext ctx) => + ContextHelpers.Pass(ctx).Db.PublicTable.Insert(default); + public static ulong Read(SpacetimeDB.ViewContext ctx) => + ContextHelpers.Pass(ctx).Db.PublicTable.Count; + public static SpacetimeDB.IQuery Query(SpacetimeDB.AnonymousViewContext ctx) => + ContextHelpers.Pass(ctx).From.PublicTable(); + } + """; + consumer += "\npublic static class ContextIdentityConsumer {" + + string.Join("\n", contextNames.Select(name => + $"public static SpacetimeDB.{name} Pass(SpacetimeDB.{name} ctx) => ContextHelpers.Pass(ctx);")) + + "}"; + compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(consumer, fixture.ParseOptions)); + Assert.Empty(GetCompilationErrors(compilation)); + AssertContextOwnership(compilation); + + var invalidWrites = CSharpSyntaxTree.ParseText(""" + public static class InvalidViewWrites + { + public static void Write(SpacetimeDB.ViewContext ctx) => ctx.Db.PublicTable.Insert(default); + public static void Write(SpacetimeDB.AnonymousViewContext ctx) => ctx.Db.PublicTable.Insert(default); + } + """, fixture.ParseOptions); + var errors = GetCompilationErrors(compilation.AddSyntaxTrees(invalidWrites)).ToArray(); + Assert.Equal(2, errors.Length); + Assert.All(errors, error => Assert.Equal("CS1061", error.Id)); + } +#endif + [Fact] public static async Task TypeAndModuleGeneratorsOnServer() { diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 0baec31b011..733d6e52577 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -907,7 +907,7 @@ public IEnumerable GenerateReadOnlyAccessors() } } - public IEnumerable GenerateQueryBuilderMembers() + public IEnumerable GenerateQueryBuilderMembers(bool useExtensions = false) { if (Kind is TypeKind.Sum) { @@ -1011,11 +1011,11 @@ string IxColInit(ColumnDeclaration col) } } - public readonly partial struct QueryBuilder + {{(useExtensions ? "public static partial class QueryTableExtensions" : "public readonly partial struct QueryBuilder")}} { - {{vis}} global::SpacetimeDB.Table<{{globalRowName}}, {{colsTypeName}}, {{ixColsTypeName}}> {{accessorIdentifier}}() => + {{(useExtensions ? " extension(global::SpacetimeDB.QueryBuilder from) {\n" : "")}} {{vis}} global::SpacetimeDB.Table<{{globalRowName}}, {{colsTypeName}}, {{ixColsTypeName}}> {{accessorIdentifier}}() => new("{{tableName}}", new {{colsTypeName}}("{{tableName}}"), new {{ixColsTypeName}}("{{tableName}}")); - } + {{(useExtensions ? " }\n" : "")}}} """; } } @@ -2529,16 +2529,21 @@ public void Initialize(IncrementalGeneratorInitializationContext context) "\n", tableDecls.Array.SelectMany(t => t.GenerateQueryBuilderMembers()) ); + var queryBuilderExtensionMembers = string.Join( + "\n", + tableDecls.Array.SelectMany(t => t.GenerateQueryBuilderMembers(useExtensions: true)) + ); if (string.IsNullOrWhiteSpace(queryBuilderMembers)) { queryBuilderMembers = "public readonly partial struct QueryBuilder { }"; } - // Don't generate the FFI boilerplate if there are no tables or reducers. + // Don't generate the FFI boilerplate if there are no tables or reducers (or procedures, or views, or ...). if ( tableAccessors.Array.IsEmpty && addReducers.Array.IsEmpty && addProcedures.Array.IsEmpty && addHttpHandlers.Array.IsEmpty + && views.Array.IsEmpty ) { return; @@ -2548,9 +2553,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) $$""" // #nullable enable - // The runtime already defines SpacetimeDB.Internal.LocalReadOnly in Runtime\Internal\Module.cs as an empty partial type. - // This is needed so every module build doesn't generate a full LocalReadOnly type, but just adds on to the existing. - // We extend it here with generated table accessors, and just need to suppress the duplicate-type warning. + // .NET 8 generates a module-local LocalReadOnly which shadows the runtime shell. #pragma warning disable CS0436 #pragma warning disable STDB_UNSTABLE @@ -2564,7 +2567,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context) using TxContext = SpacetimeDB.Internal.TxContext; namespace SpacetimeDB { + #if !NET10_0_OR_GREATER {{queryBuilderMembers}} + #endif public static class Handlers { {{string.Join("\n", addHttpHandlers.Select(r => $"public static readonly global::SpacetimeDB.Handler {EscapeIdentifier(r.Name)} = new(nameof({r.FullName}));" @@ -2643,8 +2648,6 @@ public Uuid NewUuidV7() return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); } } - #endif - public sealed partial class ProcedureContext : global::SpacetimeDB.ProcedureContextBase { public new global::SpacetimeDB.ModuleEnvironment Env => default; private readonly Local _db = new(); @@ -2769,11 +2772,9 @@ internal HandlerTxContext(Internal.TxContext inner) : base(inner) {} public new Local Db => (Local)base.Db; } - #if !NET10_0_OR_GREATER public sealed class Local : global::SpacetimeDB.LocalBase { {{string.Join("\n", tableAccessors.Select(v => v.Getter))}} } - #endif public sealed record ViewContext : DbContext, Internal.IViewContext { @@ -2797,6 +2798,7 @@ public sealed record AnonymousViewContext : DbContext, I internal AnonymousViewContext(Internal.LocalReadOnly db) : base(db) { } } + #endif } #if NET10_0_OR_GREATER @@ -2806,6 +2808,12 @@ public static class LocalTableExtensions { {{string.Join("\n", tableAccessors.Select(v => v.Getter))}} } } + public static class ReadOnlyTableExtensions { + extension(global::SpacetimeDB.Internal.LocalReadOnly db) { + {{string.Join("\n", readOnlyAccessors.Select(v => v.ReadOnlyGetter))}} + } + } + {{queryBuilderExtensionMembers}} } #endif @@ -2826,11 +2834,13 @@ namespace SpacetimeDB.Internal.ViewHandles { {{string.Join("\n", readOnlyAccessors.Array.Select(v => v.ReadOnlyAccessor))}} } + #if !NET10_0_OR_GREATER namespace SpacetimeDB.Internal { public sealed partial class LocalReadOnly { {{string.Join("\n", readOnlyAccessors.Select(v => v.ReadOnlyGetter))}} } } + #endif static class ModuleRegistration { // Module host calls are single-threaded in Wasm today, so the generated @@ -2865,11 +2875,12 @@ public static List ToListOrEmpty(T? value) where T : class public static void Main() { #if !NET10_0_OR_GREATER SpacetimeDB.Internal.Module.SetReducerContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ReducerContext(identity, connectionId, random, time)); - #endif SpacetimeDB.Internal.Module.SetViewContextConstructor(identity => new SpacetimeDB.ViewContext(identity, new SpacetimeDB.Internal.LocalReadOnly())); SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor(() => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly())); - SpacetimeDB.Internal.Module.SetProcedureContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ProcedureContext(identity, connectionId, random, time));{{preRegistrations}} + SpacetimeDB.Internal.Module.SetProcedureContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ProcedureContext(identity, connectionId, random, time)); SpacetimeDB.Internal.Module.SetHandlerContextConstructor((random, time) => new SpacetimeDB.HandlerContext(random, time)); + #endif + {{preRegistrations}} var __memoryStream = new MemoryStream(); var __writer = new BinaryWriter(__memoryStream); diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index 47b6b908466..ee19b5bca9d 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -56,10 +56,24 @@ private static Func< #else null; #endif - private static Func? newViewContext = null; - private static Func? newAnonymousViewContext = null; + private static Func? newViewContext = +#if NET10_0_OR_GREATER + identity => new ViewContext(identity, new LocalReadOnly()); +#else + null; +#endif + private static Func? newAnonymousViewContext = +#if NET10_0_OR_GREATER + () => new AnonymousViewContext(new LocalReadOnly()); +#else + null; +#endif private static Func? newHandlerContext = +#if NET10_0_OR_GREATER + (random, time) => new HandlerContext(random, time); +#else null; +#endif private static Func< Identity, @@ -67,7 +81,13 @@ private static Func< Random, Timestamp, IProcedureContext - >? newProcedureContext = null; + >? newProcedureContext = +#if NET10_0_OR_GREATER + (identity, connectionId, random, time) => + new ProcedureContext(identity, connectionId, random, time); +#else + null; +#endif public static void SetReducerContextConstructor( Func ctor @@ -391,12 +411,9 @@ public partial class Local /// /// Read-only database access for view contexts. -/// The code generator will extend this partial class to add table accessors. +/// On .NET 10 the generator provides assembly-scoped extension properties. +/// On .NET 8 generated modules declare their own type with table accessors. /// public sealed partial class LocalReadOnly { - // This class is intentionally empty - the code generator will add - // read-only table accessors for each table in the module. - // Example generated code: - // public Internal.ViewHandles.UserReadOnly User => new(); } diff --git a/crates/bindings-csharp/Runtime/ModuleContexts.cs b/crates/bindings-csharp/Runtime/ModuleContexts.cs index 2586cf711a4..1578461c38a 100644 --- a/crates/bindings-csharp/Runtime/ModuleContexts.cs +++ b/crates/bindings-csharp/Runtime/ModuleContexts.cs @@ -1,6 +1,11 @@ #if NET10_0_OR_GREATER namespace SpacetimeDB; +using System.Diagnostics.CodeAnalysis; + +#pragma warning disable STDB_UNSTABLE +#pragma warning disable CA1822 // Preserve the existing instance-based context API. + public sealed class Local : LocalBase { } public sealed record ReducerContext : DbContext, Internal.IReducerContext { @@ -73,4 +78,148 @@ public Uuid NewUuidV7() return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); } } -#endif \ No newline at end of file + +public readonly struct QueryBuilder { } + +public sealed partial class ProcedureContext : global::SpacetimeDB.ProcedureContextBase { + private readonly Local _db = new(); + + internal ProcedureContext(Identity identity, ConnectionId? connectionId, Random random, Timestamp time) + : base(identity, connectionId, random, time) {} + + protected internal override global::SpacetimeDB.LocalBase CreateLocal() => _db; + protected override global::SpacetimeDB.ProcedureTxContextBase CreateTxContext(Internal.TxContext inner) => + _cached ??= new ProcedureTxContext(inner); + + private ProcedureTxContext? _cached; + + public Local Db => _db; + + public TResult WithTx(Func body) => + base.WithTx(tx => body((ProcedureTxContext)tx)); + + public TxOutcome TryWithTx( + Func> body) + where TError : Exception => + base.TryWithTx(tx => body((ProcedureTxContext)tx)); + + /// + /// Create a new random `v4` using the built-in RNG. + /// + /// + /// This method fills the random bytes using the context RNG. + /// + /// + /// + /// var uuid = ctx.NewUuidV4(); + /// Log.Info(uuid); + /// + /// + public Uuid NewUuidV4() + { + var bytes = new byte[16]; + Rng.NextBytes(bytes); + return Uuid.FromRandomBytesV4(bytes); + } + + /// + /// Create a new sortable `v7` using the built-in RNG, monotonic counter, + /// and timestamp. + /// + /// + /// A newly generated `v7` that is monotonically ordered + /// and suitable for use as a primary key or for ordered storage. + /// + /// + /// Thrown if UUID generation fails. + /// + /// + /// + /// [SpacetimeDB.Procedure] + /// public static Guid GenerateUuidV7(ReducerContext ctx) + /// { + /// Guid uuid = ctx.NewUuidV7(); + /// Log.Info(uuid); + /// } + /// + /// + public Uuid NewUuidV7() + { + var bytes = new byte[4]; + Rng.NextBytes(bytes); + return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); + } +} + +public sealed partial class HandlerContext : global::SpacetimeDB.HandlerContextBase { + private readonly Local _db = new(); + + internal HandlerContext(Random random, Timestamp time) + : base(random, time) {} + + protected override global::SpacetimeDB.LocalBase CreateLocal() => _db; + protected override global::SpacetimeDB.HandlerTxContextBase CreateTxContext(Internal.TxContext inner) => + _cached ??= new HandlerTxContext(inner); + + private HandlerTxContext? _cached; + + [Experimental("STDB_UNSTABLE")] + public TResult WithTx(Func body) => + base.WithTx(tx => body((HandlerTxContext)tx)); + + [Experimental("STDB_UNSTABLE")] + public TxOutcome TryWithTx( + Func> body) + where TError : Exception => + base.TryWithTx(tx => body((HandlerTxContext)tx)); + + public Uuid NewUuidV4() + { + var bytes = new byte[16]; + Rng.NextBytes(bytes); + return Uuid.FromRandomBytesV4(bytes); + } + + public Uuid NewUuidV7() + { + var bytes = new byte[4]; + Rng.NextBytes(bytes); + return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); + } +} + +public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase { + internal ProcedureTxContext(Internal.TxContext inner) : base(inner) {} + + public new Local Db => (Local)base.Db; +} + +[Experimental("STDB_UNSTABLE")] +public sealed class HandlerTxContext : global::SpacetimeDB.HandlerTxContextBase { + internal HandlerTxContext(Internal.TxContext inner) : base(inner) {} + + public new Local Db => (Local)base.Db; +} + +public sealed record ViewContext : DbContext, Internal.IViewContext +{ + public Identity Sender { get; } + + public QueryBuilder From => default; + + internal ViewContext(Identity sender, Internal.LocalReadOnly db) + : base(db) + { + Sender = sender; + } +} + +public sealed record AnonymousViewContext : DbContext, Internal.IAnonymousViewContext +{ + public QueryBuilder From => default; + + internal AnonymousViewContext(Internal.LocalReadOnly db) + : base(db) { } +} + +#endif From 496771b7447252786a7465bff30195b798f3d7f3 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Tue, 15 Sep 2026 12:25:25 -0500 Subject: [PATCH 05/49] Test that publishing a project doesn't export dependencies's entrypoints --- .../tests/standalone_integration_test.rs | 26 +++++++++++++++++++ modules/root-selection-consumer-cs/Lib.cs | 14 ++++++++++ .../root-selection-consumer-cs.csproj | 13 ++++++++++ modules/root-selection-dependency-cs/Lib.cs | 14 ++++++++++ .../root-selection-dependency-cs.csproj | 13 ++++++++++ 5 files changed, 80 insertions(+) create mode 100644 modules/root-selection-consumer-cs/Lib.cs create mode 100644 modules/root-selection-consumer-cs/root-selection-consumer-cs.csproj create mode 100644 modules/root-selection-dependency-cs/Lib.cs create mode 100644 modules/root-selection-dependency-cs/root-selection-dependency-cs.csproj diff --git a/crates/testing/tests/standalone_integration_test.rs b/crates/testing/tests/standalone_integration_test.rs index 8214e527120..139da0575b4 100644 --- a/crates/testing/tests/standalone_integration_test.rs +++ b/crates/testing/tests/standalone_integration_test.rs @@ -99,6 +99,32 @@ fn test_calling_a_reducer_csharp() { test_calling_a_reducer_in_module("module-test-cs"); } +#[test] +#[serial] +fn namespace_csharp_root_selected_at_publish() { + init(); + + // Build the dependency first, then reuse its managed DLL without rebuilding or changing its project. + let dependency = CompiledModule::compile("root-selection-dependency-cs", CompilationMode::Debug); + dependency.with_module_async(DEFAULT_CONFIG, |module| async move { + module + .call_reducer_binary("dependency_entry", &product![]) + .await + .unwrap(); + assert!(module.read_log(None).await.contains("dependency published as root")); + }); + + // Both assemblies contain generated host entrypoint declarations. Only the published root's + // declarations must become native exports; otherwise publishing produces duplicate symbols. + CompiledModule::compile("root-selection-consumer-cs", CompilationMode::Debug).with_module_async( + DEFAULT_CONFIG, + |module| async move { + module.call_reducer_binary("consumer_entry", &product![]).await.unwrap(); + assert!(module.read_log(None).await.contains("consumer published as root")); + }, + ); +} + #[test] #[serial] fn test_calling_a_reducer_typescript() { diff --git a/modules/root-selection-consumer-cs/Lib.cs b/modules/root-selection-consumer-cs/Lib.cs new file mode 100644 index 00000000000..3e29a1f2870 --- /dev/null +++ b/modules/root-selection-consumer-cs/Lib.cs @@ -0,0 +1,14 @@ +using SpacetimeDB; + +public static partial class Consumer +{ + [Reducer] + public static void ConsumerEntry(ReducerContext ctx) + { + if (Dependency.Answer() != 42) + { + throw new InvalidOperationException("Referenced assembly returned the wrong result."); + } + Log.Info("consumer published as root"); + } +} diff --git a/modules/root-selection-consumer-cs/root-selection-consumer-cs.csproj b/modules/root-selection-consumer-cs/root-selection-consumer-cs.csproj new file mode 100644 index 00000000000..49a4ed4decf --- /dev/null +++ b/modules/root-selection-consumer-cs/root-selection-consumer-cs.csproj @@ -0,0 +1,13 @@ + + + net10.0 + + + + + ../root-selection-dependency-cs/bin/$(Configuration)/net10.0/wasi-wasm/RootSelectionDependency.dll + + + + + diff --git a/modules/root-selection-dependency-cs/Lib.cs b/modules/root-selection-dependency-cs/Lib.cs new file mode 100644 index 00000000000..44eb90a995f --- /dev/null +++ b/modules/root-selection-dependency-cs/Lib.cs @@ -0,0 +1,14 @@ +using System.Runtime.CompilerServices; +using SpacetimeDB; + +public static partial class Dependency +{ + [MethodImpl(MethodImplOptions.NoInlining)] + public static int Answer() => 42; + + [Reducer] + public static void DependencyEntry(ReducerContext ctx) + { + Log.Info("dependency published as root"); + } +} diff --git a/modules/root-selection-dependency-cs/root-selection-dependency-cs.csproj b/modules/root-selection-dependency-cs/root-selection-dependency-cs.csproj new file mode 100644 index 00000000000..bacc83d4a65 --- /dev/null +++ b/modules/root-selection-dependency-cs/root-selection-dependency-cs.csproj @@ -0,0 +1,13 @@ + + + net10.0 + RootSelectionDependency + + $(AssemblyName) + $(MSBuildProjectDirectory)/bin/$(Configuration)/net10.0/wasi-wasm/native/StdbModule.wasm + + + + + + From aaef1d363548a5a0d59fc8bc26cb8f7b45e68665 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Tue, 15 Sep 2026 15:42:31 -0500 Subject: [PATCH 06/49] Auto discover and register dependencies --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 241 ++++++++++++++++++ crates/bindings-csharp/Codegen/Module.cs | 158 ++++++++++-- crates/bindings-csharp/Runtime/Attrs.cs | 6 + .../Runtime/Internal/Module.cs | 1 + .../Runtime/Internal/ModuleBuilder.cs | 38 ++- 5 files changed, 396 insertions(+), 48 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 07e8b5f70e2..b157c8ef559 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -293,6 +293,247 @@ public static async Task TypeGeneratorOnClient() } #if NET10_0_OR_GREATER + [Theory] + [InlineData(false)] + [InlineData(true)] + public static async Task NamespaceDependenciesRegisterOnceInStableOrder(bool rootHasTable) + { + var fixture = await Fixture.Compile("server", "net10.0"); + const string usings = "global using System; global using System.IO; " + + "global using System.Collections.Generic; global using System.Linq;\n"; + CSharpCompilation Create(string name, string source, params MetadataReference[] references) => + CSharpCompilation.Create( + name, + [CSharpSyntaxTree.ParseText(usings + source, fixture.ParseOptions)], + fixture.SampleCompilation.References.Concat(references), + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) + ); + CSharpCompilation Generate(CSharpCompilation input) + { + var driver = CSharpGeneratorDriver.Create( + [new Type().AsSourceGenerator(), new Module().AsSourceGenerator()], + parseOptions: fixture.ParseOptions + ); + driver.RunGeneratorsAndUpdateCompilation(input, out var output, out var diagnostics); + Assert.Empty(diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error)); + Assert.Empty(GetCompilationErrors(output)); + return (CSharpCompilation)output; + } + MetadataReference Emit(CSharpCompilation compilation) + { + using var dll = new MemoryStream(); + var result = compilation.Emit(dll); + Assert.True(result.Success, string.Join("\n", result.Diagnostics)); + return MetadataReference.CreateFromImage(dll.ToArray()); + } + string Table(string name) => $$""" + namespace {{name}} { + public class Sentinel { } + [SpacetimeDB.Table] + public partial struct {{name}}Row { public uint Id; } + } + """; + string Descriptor(CSharpCompilation compilation) => Assert.Single( + compilation.GetSymbolsWithName("AssemblyDescriptor", SymbolFilter.Type) + ).ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + MethodDeclarationSyntax Method(CSharpCompilation compilation, string name) => Assert.Single( + compilation.SyntaxTrees.SelectMany(tree => tree.GetRoot().DescendantNodes()) + .OfType() + .Where(type => type.Identifier.ValueText == "ModuleRegistration") + .SelectMany(type => type.Members.OfType()) + .Where(method => method.Identifier.ValueText == name) + ); + + var sharedCompilation = Generate(Create("Shared", Table("Shared"))); + var shared = Emit(sharedCompilation); + var alphaCompilation = Generate(Create("Alpha", Table("Alpha") + + "public class AlphaLink { public Shared.Sentinel Value; }", shared)); + var alpha = Emit(alphaCompilation); + var betaCompilation = Generate(Create("Beta", Table("Beta") + + "public class BetaLink { public Shared.Sentinel Value; }", shared)); + var beta = Emit(betaCompilation); + var utility = Emit(Create("Utility", + "public class UtilityLink { public Shared.Sentinel Value; }", shared)); + var rootSource = rootHasTable ? Table("Root") : ""; + var root = Generate(Create("Root", rootSource, beta, utility, shared, alpha)); + var reordered = Generate(Create("Root", rootSource, alpha, shared, utility, beta)); + Emit(root); + Emit(reordered); + + string[] Calls(CSharpCompilation compilation) => + [.. Method(compilation, "Main").DescendantNodes() + .OfType() + .Select(call => call.Expression.ToString())]; + var expected = new[] + { + Descriptor(root) + ".Register", + Descriptor(alphaCompilation) + ".Register", + Descriptor(betaCompilation) + ".Register", + Descriptor(sharedCompilation) + ".Register", + }; + Assert.Equal(expected, Calls(root)); + Assert.Equal(expected, Calls(reordered)); + Assert.DoesNotContain(Method(root, "Register").DescendantNodes() + .OfType(), call => + call.Expression.ToString().Contains("AssemblyDescriptor.Register")); + + // An unrelated utility alone must not cause an otherwise empty module to register. + var plainUtility = Emit(Create("PlainUtility", "public class PlainUtility { }")); + var empty = Generate(Create("Empty", "", plainUtility)); + Assert.Empty(empty.GetSymbolsWithName("AssemblyDescriptor", SymbolFilter.Type)); + } + + [Fact] + // A separately compiled consumer can call the descriptor, registration populates only the supplied builder, and two builders receive identical metadata without modifying the static root. + public static async Task NamespaceDescriptorCrossAssemblyRegistration() + { + var fixture = await Fixture.Compile("server", "net10.0"); + var compilation = fixture.SampleCompilation; + foreach (var generator in new IIncrementalGenerator[] { new Type(), new Module() }) + { + compilation = compilation.AddSyntaxTrees( + fixture.RunGeneratorAndGetResult(generator).GeneratedTrees + ); + } + using var moduleDll = new MemoryStream(); + var moduleEmit = compilation.Emit(moduleDll); + Assert.True(moduleEmit.Success, string.Join("\n", moduleEmit.Diagnostics)); + + var moduleReference = MetadataReference.CreateFromImage(moduleDll.ToArray()); + var consumer = CSharpCompilation.Create( + "DescriptorConsumer", + references: fixture.SampleCompilation.References.Append(moduleReference), + options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) + ); + var moduleAssembly = (IAssemblySymbol)consumer.GetAssemblyOrModuleSymbol(moduleReference)!; + var markerType = consumer.GetTypeByMetadataName("SpacetimeDB.ModuleDescriptorAttribute"); + Assert.NotNull(markerType); + var marker = Assert.Single(moduleAssembly.GetAttributes().Where(attribute => + SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, markerType) + )); + var argument = Assert.Single(marker.ConstructorArguments); + Assert.Equal(TypedConstantKind.Type, argument.Kind); + var descriptor = Assert.IsAssignableFrom(argument.Value); + Assert.Equal(TypeKind.Class, descriptor.TypeKind); + Assert.True(descriptor.IsStatic); + Assert.Equal(Accessibility.Public, descriptor.DeclaredAccessibility); + Assert.Equal("AssemblyDescriptor", descriptor.Name); + Assert.True(SymbolEqualityComparer.Default.Equals( + moduleAssembly, descriptor.ContainingAssembly + )); + var descriptorName = descriptor.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + + var consumerSource = $$""" + using System.IO; + using System.Linq; + using System.Reflection; + using SpacetimeDB.Internal; + + public static class DescriptorConsumer + { + public static void Register(ModuleBuilder builder) => + {{descriptorName}}.Register(builder); + + private static RawModuleDefV10 Describe(ModuleBuilder builder) => + (RawModuleDefV10)typeof(ModuleBuilder).GetMethod( + "BuildModuleDefinition", BindingFlags.Instance | BindingFlags.NonPublic + )!.Invoke(builder, null)!; + + public static byte[] Snapshot(ModuleBuilder builder) + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new RawModuleDefV10.BSATN().Write(writer, Describe(builder)); + return stream.ToArray(); + } + + public static string[] TableNames(ModuleBuilder builder) => + Describe(builder).Sections.OfType() + .SelectMany(section => section.Tables_) + .Select(table => table.SourceName).ToArray(); + + public static string[] ReducerNames(ModuleBuilder builder) => + Describe(builder).Sections.OfType() + .SelectMany(section => section.Reducers_) + .Select(reducer => reducer.SourceName).ToArray(); + } + """; + consumer = consumer.AddSyntaxTrees( + CSharpSyntaxTree.ParseText(consumerSource, fixture.ParseOptions) + ); + using var consumerDll = new MemoryStream(); + var consumerEmit = consumer.Emit(consumerDll); + Assert.True(consumerEmit.Success, string.Join("\n", consumerEmit.Diagnostics)); + + // Isolate the module's static root and Runtime types from other tests. + var loadContext = new System.Runtime.Loader.AssemblyLoadContext( + nameof(NamespaceDescriptorCrossAssemblyRegistration), isCollectible: true + ); + loadContext.Resolving += (_, name) => + { + if (!name.Name!.StartsWith("SpacetimeDB.")) + { + return null; + } + var reference = fixture.SampleCompilation.References.Single(r => + fixture.SampleCompilation.GetAssemblyOrModuleSymbol(r)?.Name == name.Name + ); + if (reference is CompilationReference projectReference) + { + using var implementation = new MemoryStream(); + var result = projectReference.Compilation.Emit(implementation); + Assert.True(result.Success, string.Join("\n", result.Diagnostics)); + implementation.Position = 0; + return loadContext.LoadFromStream(implementation); + } + var path = ((PortableExecutableReference)reference).FilePath!; + // Reference assemblies cannot execute; use the sibling implementation assembly. + var directory = new DirectoryInfo(Path.GetDirectoryName(path)!); + if (directory.Name is "ref" or "refint") + { + path = Path.Combine(directory.Parent!.FullName, Path.GetFileName(path)); + } + return loadContext.LoadFromAssemblyPath(path); + }; + try + { + moduleDll.Position = 0; + loadContext.LoadFromStream(moduleDll); + consumerDll.Position = 0; + var consumerType = loadContext.LoadFromStream(consumerDll) + .GetType("DescriptorConsumer", throwOnError: true)!; + var register = consumerType.GetMethod("Register")!; + var builderType = register.GetParameters()[0].ParameterType; + var first = Activator.CreateInstance(builderType)!; + var second = Activator.CreateInstance(builderType)!; + var root = builderType.Assembly.GetType("SpacetimeDB.Internal.Module")! + .GetProperty("RootBuilder")!.GetValue(null)!; + byte[] Snapshot(object builder) => (byte[])consumerType.GetMethod("Snapshot")! + .Invoke(null, [builder])!; + var empty = Snapshot(second); + var rootBefore = Snapshot(root); + + register.Invoke(null, [first]); + Assert.Contains("PublicTable", (string[])consumerType.GetMethod("TableNames")! + .Invoke(null, [first])!); + Assert.Contains("InsertData", (string[])consumerType.GetMethod("ReducerNames")! + .Invoke(null, [first])!); + var registered = Snapshot(first); + Assert.False(empty.SequenceEqual(registered)); + Assert.Equal(empty, Snapshot(second)); + Assert.Equal(rootBefore, Snapshot(root)); + + register.Invoke(null, [second]); + Assert.Equal(registered, Snapshot(second)); + Assert.Equal(registered, Snapshot(first)); + Assert.Equal(rootBefore, Snapshot(root)); + } + finally + { + loadContext.Unload(); + } + } + [Fact] // Can a separately compiled DLL accept our module’s contexts, and can module code still access tables through the contexts it returns? public static async Task NamespaceContextsCrossAssemblyBoundaries() diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 733d6e52577..ddfc00b7e26 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -1,8 +1,10 @@ namespace SpacetimeDB.Codegen; using System; +using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -1392,7 +1394,7 @@ public string GenerateViewDef(uint Index) return null; } - return $"SpacetimeDB.Internal.Module.RegisterViewPrimaryKey(\"{EscapeStringLiteral(Name)}\", [\"{EscapeStringLiteral(PrimaryKey)}\"]);"; + return $"builder.RegisterViewPrimaryKey(\"{EscapeStringLiteral(Name)}\", [\"{EscapeStringLiteral(PrimaryKey)}\"]);"; } /// @@ -2016,9 +2018,80 @@ DiagReporter diag } } +record AssemblyDeclaration(string Identity, string DescriptorTypeName); + [Generator] public class Module : IIncrementalGenerator { + private static EquatableArray DiscoverAssemblies( + Compilation compilation, + CancellationToken cancellationToken + ) + { + cancellationToken.ThrowIfCancellationRequested(); + if ( + !compilation.SyntaxTrees.Any(tree => + tree.Options is CSharpParseOptions options + && options.PreprocessorSymbolNames.Contains("NET10_0_OR_GREATER") + ) + ) + { + return new(ImmutableArray.Empty); + } + + var markerType = compilation.GetTypeByMetadataName("SpacetimeDB.ModuleDescriptorAttribute"); + if (markerType is null) + { + return new(ImmutableArray.Empty); + } + + var visited = new HashSet { compilation.Assembly.Identity }; + var pending = new Stack(compilation.SourceModule.ReferencedAssemblySymbols); + var assemblies = new List(); + while (pending.Count > 0) + { + cancellationToken.ThrowIfCancellationRequested(); + var assembly = pending.Pop(); + if (!visited.Add(assembly.Identity)) + { + continue; + } + + // Unmarked utility assemblies may reference contributing modules. + foreach (var module in assembly.Modules) + { + foreach (var reference in module.ReferencedAssemblySymbols) + { + pending.Push(reference); + } + } + + var marker = assembly.GetAttributes().FirstOrDefault(attribute => + SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, markerType) + ); + if ( + marker is null + || marker.ConstructorArguments.Length != 1 + || marker.ConstructorArguments[0].Kind != TypedConstantKind.Type + || marker.ConstructorArguments[0].Value is not INamedTypeSymbol descriptor + ) + { + continue; + } + + assemblies.Add( + new AssemblyDeclaration( + assembly.Identity.ToString(), + descriptor.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + ) + ); + } + + return new( + assemblies.OrderBy(assembly => assembly.Identity, StringComparer.Ordinal).ToImmutableArray() + ); + } + private static string EscapeStringLiteral(string s) => s.Replace("\\", "\\\\") .Replace("\"", "\\\"") @@ -2415,14 +2488,16 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Select(c => ((int)c).ToString("X4")) ) ); + + var referencedAssemblies = context.CompilationProvider.Select(DiscoverAssemblies); // Register the generated source code with the compilation context as part of module publishing // Once the compilation is complete, the generated code will be used to create tables and reducers in the database context.RegisterSourceOutput( - moduleOutputInputs.Combine(extensionNamespace), + moduleOutputInputs.Combine(extensionNamespace).Combine(referencedAssemblies), (context, input) => { - var (inputs, extensionNamespaceName) = input; + var ((inputs, extensionNamespaceName), assemblies) = input; var ( tableAccessors, @@ -2459,7 +2534,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var settingsRegistration = settings.Array.Length == 1 && settings.Array[0].CaseConversionPolicy is { } policyName - ? $"SpacetimeDB.Internal.Module.SetCaseConversionPolicy(SpacetimeDB.CaseConversionPolicy.{policyName});" + ? $"builder.SetCaseConversionPolicy(SpacetimeDB.CaseConversionPolicy.{policyName});" : string.Empty; var explicitTableRegistrations = string.Join( @@ -2467,7 +2542,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) tableDecls.Array.SelectMany(t => t.TableAccessors.Where(a => !string.IsNullOrEmpty(a.CanonicalName)) .Select(a => - $"SpacetimeDB.Internal.Module.RegisterExplicitTableName(\"{EscapeStringLiteral(a.Name)}\", \"{EscapeStringLiteral(a.CanonicalName!)}\");" + $"builder.RegisterExplicitTableName(\"{EscapeStringLiteral(a.Name)}\", \"{EscapeStringLiteral(a.CanonicalName!)}\");" ) ) ); @@ -2477,20 +2552,20 @@ public void Initialize(IncrementalGeneratorInitializationContext context) addReducers .Array.Where(r => !string.IsNullOrEmpty(r.CanonicalName)) .Select(r => - $"SpacetimeDB.Internal.Module.RegisterExplicitFunctionName(\"{EscapeStringLiteral(r.Name)}\", \"{EscapeStringLiteral(r.CanonicalName!)}\");" + $"builder.RegisterExplicitFunctionName(\"{EscapeStringLiteral(r.Name)}\", \"{EscapeStringLiteral(r.CanonicalName!)}\");" ) .Concat( addProcedures .Array.Where(p => !string.IsNullOrEmpty(p.CanonicalName)) .Select(p => - $"SpacetimeDB.Internal.Module.RegisterExplicitFunctionName(\"{EscapeStringLiteral(p.Name)}\", \"{EscapeStringLiteral(p.CanonicalName!)}\");" + $"builder.RegisterExplicitFunctionName(\"{EscapeStringLiteral(p.Name)}\", \"{EscapeStringLiteral(p.CanonicalName!)}\");" ) ) .Concat( views .Array.Where(v => !string.IsNullOrEmpty(v.CanonicalName)) .Select(v => - $"SpacetimeDB.Internal.Module.RegisterExplicitFunctionName(\"{EscapeStringLiteral(v.Name)}\", \"{EscapeStringLiteral(v.CanonicalName!)}\");" + $"builder.RegisterExplicitFunctionName(\"{EscapeStringLiteral(v.Name)}\", \"{EscapeStringLiteral(v.CanonicalName!)}\");" ) ) ); @@ -2502,7 +2577,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) t.GetIndexes(a) .Where(ix => !string.IsNullOrEmpty(ix.CanonicalName)) .Select(ix => - $"SpacetimeDB.Internal.Module.RegisterExplicitIndexName(\"{EscapeStringLiteral(ix.StandardIndexName(a))}\", \"{EscapeStringLiteral(ix.CanonicalName!)}\");" + $"builder.RegisterExplicitIndexName(\"{EscapeStringLiteral(ix.StandardIndexName(a))}\", \"{EscapeStringLiteral(ix.CanonicalName!)}\");" ) ) ) @@ -2544,6 +2619,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) && addProcedures.Array.IsEmpty && addHttpHandlers.Array.IsEmpty && views.Array.IsEmpty + && assemblies.Array.IsEmpty ) { return; @@ -2565,6 +2641,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context) using System.Runtime.InteropServices; using Internal = SpacetimeDB.Internal; using TxContext = SpacetimeDB.Internal.TxContext; + + #if NET10_0_OR_GREATER + [assembly: global::SpacetimeDB.ModuleDescriptorAttribute( + typeof(global::{{extensionNamespaceName}}.AssemblyDescriptor))] + #endif namespace SpacetimeDB { #if !NET10_0_OR_GREATER @@ -2803,6 +2884,11 @@ internal AnonymousViewContext(Internal.LocalReadOnly db) #if NET10_0_OR_GREATER namespace {{extensionNamespaceName}} { + public static class AssemblyDescriptor { + public static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder) + => global::ModuleRegistration.Register(builder); + } public static class LocalTableExtensions { extension(global::SpacetimeDB.Local db) { {{string.Join("\n", tableAccessors.Select(v => v.Getter))}} @@ -2873,33 +2959,49 @@ public static List ToListOrEmpty(T? value) where T : class [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, typeof(ModuleRegistration))] #endif public static void Main() { - #if !NET10_0_OR_GREATER - SpacetimeDB.Internal.Module.SetReducerContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ReducerContext(identity, connectionId, random, time)); - SpacetimeDB.Internal.Module.SetViewContextConstructor(identity => new SpacetimeDB.ViewContext(identity, new SpacetimeDB.Internal.LocalReadOnly())); - SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor(() => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly())); - SpacetimeDB.Internal.Module.SetProcedureContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ProcedureContext(identity, connectionId, random, time)); - SpacetimeDB.Internal.Module.SetHandlerContextConstructor((random, time) => new SpacetimeDB.HandlerContext(random, time)); - #endif - {{preRegistrations}} - var __memoryStream = new MemoryStream(); - var __writer = new BinaryWriter(__memoryStream); + #if !NET10_0_OR_GREATER + SpacetimeDB.Internal.Module.SetReducerContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ReducerContext(identity, connectionId, random, time)); + SpacetimeDB.Internal.Module.SetViewContextConstructor(identity => new SpacetimeDB.ViewContext(identity, new SpacetimeDB.Internal.LocalReadOnly())); + SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor(() => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly())); + SpacetimeDB.Internal.Module.SetProcedureContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ProcedureContext(identity, connectionId, random, time)); + SpacetimeDB.Internal.Module.SetHandlerContextConstructor((random, time) => new SpacetimeDB.HandlerContext(random, time)); + #endif + + #if NET10_0_OR_GREATER + global::{{extensionNamespaceName}}.AssemblyDescriptor.Register( + global::SpacetimeDB.Internal.Module.RootBuilder); + {{string.Join("\n", + assemblies.Array.Select(a => + $"{a.DescriptorTypeName}.Register(global::SpacetimeDB.Internal.Module.RootBuilder);") + )}} + #else + Register(global::SpacetimeDB.Internal.Module.RootBuilder); + #endif + } + + internal static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder) + { + {{preRegistrations}} + var __memoryStream = new MemoryStream(); + var __writer = new BinaryWriter(__memoryStream); {{string.Join( "\n", addReducers.Select(r => - $"SpacetimeDB.Internal.Module.RegisterReducer<{EscapeIdentifier(r.Name)}>();" + $"builder.RegisterReducer<{EscapeIdentifier(r.Name)}>();" ) )}} {{string.Join( "\n", addProcedures.Select(r => - $"SpacetimeDB.Internal.Module.RegisterProcedure<{EscapeIdentifier(r.Name)}>();" + $"builder.RegisterProcedure<{EscapeIdentifier(r.Name)}>();" ) )}} {{string.Join( "\n", addHttpHandlers.Select(r => - $"SpacetimeDB.Internal.Module.RegisterHttpHandler<{EscapeIdentifier(r.Name)}>();" + $"builder.RegisterHttpHandler<{EscapeIdentifier(r.Name)}>();" ) )}} @@ -2908,10 +3010,10 @@ public static void Main() { // See the comment on `GenerateDispatcherClass` for more explanation. {{string.Join("\n", views.Array.Where(v => !v.IsAnonymous) - .Select(v => $"SpacetimeDB.Internal.Module.RegisterView<{v.Name}ViewDispatcher>();") + .Select(v => $"builder.RegisterView<{v.Name}ViewDispatcher>();") .Concat( views.Array.Where(v => v.IsAnonymous) - .Select(v => $"SpacetimeDB.Internal.Module.RegisterAnonymousView<{v.Name}ViewDispatcher>();") + .Select(v => $"builder.RegisterAnonymousView<{v.Name}ViewDispatcher>();") ) )}} @@ -2922,16 +3024,16 @@ public static void Main() { {{string.Join( "\n", - tableAccessors.Select(t => $"SpacetimeDB.Internal.Module.RegisterTable<{t.TableName}, SpacetimeDB.Internal.TableHandles.{EscapeIdentifier(t.TableAccessorName)}>();") + tableAccessors.Select(t => $"builder.RegisterTable<{t.TableName}, SpacetimeDB.Internal.TableHandles.{EscapeIdentifier(t.TableAccessorName)}>();") )}} {{( httpRouters.Array.FirstOrDefault(r => r.IsValid) is { } router - ? $"SpacetimeDB.Internal.Module.RegisterHttpRouter({router.FullName}());" + ? $"builder.RegisterHttpRouter({router.FullName}());" : string.Empty )}} {{string.Join( "\n", - rlsFilters.Select(f => $"SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter({f.GlobalName});") + rlsFilters.Select(f => $"builder.RegisterClientVisibilityFilter({f.GlobalName});") )}} {{string.Join( "\n", @@ -2942,7 +3044,7 @@ public static void Main() { + "__memoryStream.SetLength(0);\n" + $"value.Write(__writer, {d.Value});\n" + "var array = __memoryStream.ToArray();\n" - + $"SpacetimeDB.Internal.Module.RegisterTableDefaultValue(\"{d.TableName}\", {d.ColumnId}, array);" + + $"builder.RegisterTableDefaultValue(\"{d.TableName}\", {d.ColumnId}, array);" + "\n}\n") )}} } diff --git a/crates/bindings-csharp/Runtime/Attrs.cs b/crates/bindings-csharp/Runtime/Attrs.cs index c8ce86aa2d9..d80caa3d7be 100644 --- a/crates/bindings-csharp/Runtime/Attrs.cs +++ b/crates/bindings-csharp/Runtime/Attrs.cs @@ -229,4 +229,10 @@ public sealed class HttpHandlerAttribute() : Attribute { } [AttributeUsage(AttributeTargets.Method, Inherited = false)] public sealed class HttpRouterAttribute() : Attribute { } + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)] + public sealed class ModuleDescriptorAttribute(Type descriptorType) : Attribute + { + public Type DescriptorType { get; } = descriptorType; + } } diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index ee19b5bca9d..9750c414d69 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -42,6 +42,7 @@ private static void EnsureNativeAotTypeRoots() } private static readonly ModuleBuilder moduleDef = new(); + public static ModuleBuilder RootBuilder => moduleDef; private static Func< Identity, diff --git a/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs b/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs index 2548d6ce6b6..2f0cc831bbd 100644 --- a/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs +++ b/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs @@ -5,11 +5,11 @@ namespace SpacetimeDB.Internal; using System.Linq; using SpacetimeDB.BSATN; -internal sealed class ModuleBuilder +public sealed class ModuleBuilder { - internal Module.TypeRegistrar TypeRegistrar { get; } + private Module.TypeRegistrar TypeRegistrar { get; } - internal ModuleBuilder() => TypeRegistrar = new Module.TypeRegistrar(this); + public ModuleBuilder() => TypeRegistrar = new Module.TypeRegistrar(this); private static class ReducerCache where R : IReducer, new() @@ -95,7 +95,7 @@ internal AlgebraicType.Ref RegisterType( return typeRef; } - internal void RegisterReducer() + public void RegisterReducer() where R : IReducer, new() { var reducer = ReducerCache.Instance; @@ -114,7 +114,7 @@ internal void RegisterReducer(RawReducerDefV10 reducer, Lifecycle? lifecycle) } } - internal void RegisterProcedure

() + public void RegisterProcedure

() where P : IProcedure, new() { var procedure = ProcedureCache

.Instance; @@ -123,7 +123,7 @@ internal void RegisterProcedure

() internal void RegisterProcedure(RawProcedureDefV10 procedure) => procedureDefs.Add(procedure); - internal void RegisterHttpHandler() + public void RegisterHttpHandler() where H : IHttpHandler, new() { var handler = HttpHandlerCache.Instance; @@ -132,7 +132,7 @@ internal void RegisterHttpHandler() internal void RegisterHttpHandler(RawHttpHandlerDefV10 handler) => httpHandlerDefs.Add(handler); - internal void RegisterHttpRouter(SpacetimeDB.Router router) + public void RegisterHttpRouter(SpacetimeDB.Router router) { foreach (var route in router.GetRoutes()) { @@ -159,12 +159,10 @@ internal bool HasHttpHandler(string sourceName) => internal void RegisterHttpRoute(RawHttpRouteDefV10 route) => httpRouteDefs.Add(route); - internal void RegisterTable() + public void RegisterTable() where T : IStructuralReadWrite, new() - where View : ITableView, new() - { + where View : ITableView, new() => RegisterTable(View.MakeTableDesc(TypeRegistrar), View.MakeScheduleDesc()); - } internal void RegisterTable(RawTableDefV10 table, RawScheduleDefV10? schedule) { @@ -175,7 +173,7 @@ internal void RegisterTable(RawTableDefV10 table, RawScheduleDefV10? schedule) } } - internal void RegisterView() + public void RegisterView() where TDispatcher : IView, new() { var dispatcher = ViewDispatcherCache.Instance; @@ -183,7 +181,7 @@ internal void RegisterView() RegisterView(def); } - internal void RegisterAnonymousView() + public void RegisterAnonymousView() where TDispatcher : IAnonymousView, new() { var dispatcher = AnonymousViewDispatcherCache.Instance; @@ -196,10 +194,10 @@ internal void RegisterAnonymousView() internal void RegisterEnvironment(EnvironmentDeclaration declaration) => environment.Add(declaration); - internal void RegisterViewPrimaryKey(string viewSourceName, IEnumerable columns) => + public void RegisterViewPrimaryKey(string viewSourceName, IEnumerable columns) => viewPrimaryKeyDefs.Add(new RawViewPrimaryKeyDefV10(viewSourceName, [.. columns])); - internal void RegisterClientVisibilityFilter(Filter rlsFilter) + public void RegisterClientVisibilityFilter(Filter rlsFilter) { if (rlsFilter is Filter.Sql(var rlsSql)) { @@ -214,7 +212,7 @@ internal void RegisterClientVisibilityFilter(Filter rlsFilter) internal void RegisterRowLevelSecurity(RawRowLevelSecurityDefV9 rls) => rowLevelSecurityDefs.Add(rls); - internal void RegisterTableDefaultValue(string table, ushort colId, byte[] value) + public void RegisterTableDefaultValue(string table, ushort colId, byte[] value) { if (!defaultValuesByTable.TryGetValue(table, out var defaults)) { @@ -224,18 +222,18 @@ internal void RegisterTableDefaultValue(string table, ushort colId, byte[] value defaults.Add(new RawColumnDefaultValueV10(colId, [.. value])); } - internal void SetCaseConversionPolicy(SpacetimeDB.CaseConversionPolicy policy) => + public void SetCaseConversionPolicy(SpacetimeDB.CaseConversionPolicy policy) => caseConversionPolicy = policy; - internal void RegisterExplicitTableName(string sourceName, string canonicalName) => + public void RegisterExplicitTableName(string sourceName, string canonicalName) => explicitNames.Add(new ExplicitNameEntry.Table(new NameMapping(sourceName, canonicalName))); - internal void RegisterExplicitFunctionName(string sourceName, string canonicalName) => + public void RegisterExplicitFunctionName(string sourceName, string canonicalName) => explicitNames.Add( new ExplicitNameEntry.Function(new NameMapping(sourceName, canonicalName)) ); - internal void RegisterExplicitIndexName(string sourceName, string canonicalName) => + public void RegisterExplicitIndexName(string sourceName, string canonicalName) => explicitNames.Add(new ExplicitNameEntry.Index(new NameMapping(sourceName, canonicalName))); internal RawModuleDefV10 BuildModuleDefinition() From 14a54f05c74d8df49a55835c6b46ecec6ea036ce Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Wed, 16 Sep 2026 13:23:36 -0500 Subject: [PATCH 07/49] Add namespace declaration and registration --- .../Codegen.Tests/Codegen.Tests.csproj | 9 +- .../bindings-csharp/Codegen.Tests/TestInit.cs | 41 +- crates/bindings-csharp/Codegen.Tests/Tests.cs | 314 ++++++++++- crates/bindings-csharp/Codegen/Diag.cs | 31 ++ crates/bindings-csharp/Codegen/Module.cs | 521 ++++++++++++++---- .../Codegen/NamespaceDeclaration.cs | 147 +++++ crates/bindings-csharp/Runtime/Attrs.cs | 19 + .../Runtime/Internal/ITable.cs | 4 +- .../Runtime/Internal/Module.cs | 13 + .../Runtime/Internal/ModuleBuilder.cs | 11 +- .../Runtime/Internal/NamespaceRegistry.cs | 27 + .../tests/standalone_integration_test.rs | 73 +++ modules/namespace-test-cs/Lib.cs | 60 ++ .../libraries/AuditLib/AuditLib.csproj | 11 + .../libraries/AuditLib/Lib.cs | 23 + .../libraries/AuthLib/AuthLib.csproj | 11 + .../libraries/AuthLib/Lib.cs | 49 ++ .../libraries/ExtraLib/ExtraLib.csproj | 11 + .../libraries/ExtraLib/Lib.cs | 19 + .../namespace-test-cs.csproj | 13 + 20 files changed, 1273 insertions(+), 134 deletions(-) create mode 100644 crates/bindings-csharp/Codegen/NamespaceDeclaration.cs create mode 100644 crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs create mode 100644 modules/namespace-test-cs/Lib.cs create mode 100644 modules/namespace-test-cs/libraries/AuditLib/AuditLib.csproj create mode 100644 modules/namespace-test-cs/libraries/AuditLib/Lib.cs create mode 100644 modules/namespace-test-cs/libraries/AuthLib/AuthLib.csproj create mode 100644 modules/namespace-test-cs/libraries/AuthLib/Lib.cs create mode 100644 modules/namespace-test-cs/libraries/ExtraLib/ExtraLib.csproj create mode 100644 modules/namespace-test-cs/libraries/ExtraLib/Lib.cs create mode 100644 modules/namespace-test-cs/namespace-test-cs.csproj diff --git a/crates/bindings-csharp/Codegen.Tests/Codegen.Tests.csproj b/crates/bindings-csharp/Codegen.Tests/Codegen.Tests.csproj index 0f7a1bfc47f..ee5a32e04ad 100644 --- a/crates/bindings-csharp/Codegen.Tests/Codegen.Tests.csproj +++ b/crates/bindings-csharp/Codegen.Tests/Codegen.Tests.csproj @@ -17,7 +17,6 @@ - @@ -26,6 +25,7 @@ + @@ -35,9 +35,10 @@ - - - + + + + diff --git a/crates/bindings-csharp/Codegen.Tests/TestInit.cs b/crates/bindings-csharp/Codegen.Tests/TestInit.cs index 9ceb6a3cfa8..aff6f194409 100644 --- a/crates/bindings-csharp/Codegen.Tests/TestInit.cs +++ b/crates/bindings-csharp/Codegen.Tests/TestInit.cs @@ -3,10 +3,34 @@ namespace SpacetimeDB.Codegen.Tests; using System.Runtime.CompilerServices; using System.Text; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; // Global Verify setup for all tests we might have. static class TestInit { + internal static (string Code, IEnumerable Errors) FormatCode(string code) + { + var header = ""; + // CSharpier reorders conditional global imports below ordinary imports. + // Keep this already-formatted header intact and format the declarations only. + if (code.Contains("global using ")) + { + var root = CSharpSyntaxTree.ParseText(code).GetCompilationUnitRoot(); + var headerEnd = root.Usings.Last().FullSpan.End; + header = code[..headerEnd]; + code = code[headerEnd..]; + } + var result = CSharpier.Core.CSharp.CSharpFormatter.Format( + code, + new() { IncludeGenerated = true, EndOfLine = CSharpier.Core.EndOfLine.LF } + ); +#if NET10_0_OR_GREATER + return (header + result.Code, result.ErrorDiagnostics); +#else + return (header + result.Code, result.CompilationErrors); +#endif + } + // A custom Diagnostic converter that pretty-prints the error with the source code snippet and squiggly underline. // TODO: upstream this? class DiagConverter : WriteOnlyJsonConverter @@ -72,26 +96,15 @@ public static void Initialize() (sb) => { var unformattedCode = sb.ToString(); - // CSharpier 0.28 cannot preserve C# 14 extension declarations, even in inactive branches. - // Only trim trailing whitespace; generator tests compile the original syntax trees. - if (unformattedCode.Contains("extension(global::SpacetimeDB.Local db)")) - { - sb.Clear(); - sb.Append(string.Join("\n", unformattedCode.Split('\n').Select(line => line.TrimEnd()))); - return; - } sb.Clear(); - var result = CSharpier.CodeFormatter.Format( - unformattedCode, - new() { IncludeGenerated = true, EndOfLine = CSharpier.EndOfLine.LF } - ); + var result = FormatCode(unformattedCode); sb.Append(result.Code); // Print errors in the end so that their line numbers are still meaningful. - if (result.CompilationErrors.Any()) + if (result.Errors.Any()) { sb.AppendLine(); sb.AppendLine("// Generated code produced compilation errors:"); - foreach (var diag in result.CompilationErrors) + foreach (var diag in result.Errors) { sb.Append("// ").AppendLine(diag.ToString()); } diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index b157c8ef559..2cfb1eb1bb6 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -280,6 +280,155 @@ public static async Task NamespaceProofPreservesNet8RootExamples() } } + [Theory] + [InlineData("server")] + [InlineData("explicitnames")] + public static async Task FormattedGeneratedCodeCompiles(string fixtureName) + { + var fixture = await Fixture.Compile(fixtureName); + var compilation = fixture.SampleCompilation; + foreach (var generator in new IIncrementalGenerator[] { new Type(), new Module() }) + { + foreach (var tree in fixture.RunGeneratorAndGetResult(generator).GeneratedTrees) + { + var formatted = TestInit.FormatCode(tree.ToString()); + Assert.Empty(formatted.Errors); + compilation = compilation.AddSyntaxTrees( + CSharpSyntaxTree.ParseText( + formatted.Code, + fixture.ParseOptions, + path: tree.FilePath + ) + ); + } + } + Assert.Empty(GetCompilationErrors(compilation)); + AssertContextOwnership(compilation); + } + + [Fact] + public static async Task NamespaceDeclarationsParseAndValidate() + { + var fixture = await Fixture.Compile("server"); + const string usings = "global using System; global using System.IO; " + + "global using System.Collections.Generic; global using System.Linq;\n"; + CSharpCompilation Create(string name, string source, params MetadataReference[] references) => + CSharpCompilation.Create( + name, + [CSharpSyntaxTree.ParseText(usings + source, fixture.ParseOptions)], + fixture.SampleCompilation.References.Concat(references), + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) + ); + MetadataReference Dependency(string name) + { + var compilation = Create(name, $$""" + namespace {{name}} { + public class Marker { } + [SpacetimeDB.Table(Accessor = "{{name}}Row")] + public partial struct Row { public uint Id; } + } + """); + var driver = CSharpGeneratorDriver.Create( + [new Type().AsSourceGenerator(), new Module().AsSourceGenerator()], + parseOptions: fixture.ParseOptions + ); + driver.RunGeneratorsAndUpdateCompilation(compilation, out var output, out var diagnostics); + Assert.Empty(diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error)); + using var dll = new MemoryStream(); + var emitted = output.Emit(dll); + Assert.True(emitted.Success, string.Join("\n", emitted.Diagnostics)); + return MetadataReference.CreateFromImage(dll.ToArray()); + } + var auth = Dependency("Auth"); + var audit = Dependency("Audit"); + string Mount(string marker = "Auth.Marker", string accessor = "MyAuth", string name = "auth_data") => + $"[assembly: SpacetimeDB.Namespace(typeof({marker}), Accessor = \"{accessor}\", Name = \"{name}\")]\n"; + GeneratorDriver Run(string source) => CSharpGeneratorDriver.Create( + [new Module().AsSourceGenerator()], + parseOptions: fixture.ParseOptions, + driverOptions: new GeneratorDriverOptions( + IncrementalGeneratorOutputKind.None, + trackIncrementalGeneratorSteps: true + ) + ).RunGenerators(Create("Consumer", source, auth, audit)); +#if NET10_0_OR_GREATER + void Reject(string source, string message) + { + var diagnostics = Run(source).GetRunResult().Diagnostics; + Assert.Contains(diagnostics, d => d.GetMessage().Contains(message)); + Assert.All(diagnostics, d => Assert.True(d.Location.IsInSource, d.ToString())); + } + + object[] Parsed(GeneratorDriver driver) => [.. driver.GetRunResult().Results.Single() + .TrackedSteps["SpacetimeDB.Namespace.Parse"].Single().Outputs + .SelectMany(o => ((System.Collections.IEnumerable)o.Value).Cast())]; + foreach (var accessor in new[] { "MyAuth", "class", "event" }) + { + var driver = Run(Mount(accessor: accessor)); + Assert.Empty(driver.GetRunResult().Diagnostics); + var declaration = Assert.Single(Parsed(driver)); + Assert.Equal("auth_data", declaration.GetType().GetProperty("Name")!.GetValue(declaration)); + Assert.Equal(accessor, declaration.GetType().GetProperty("Accessor")!.GetValue(declaration)); + Assert.Equal( + accessor == "MyAuth" ? accessor : "@" + accessor, + declaration.GetType().GetProperty("AccessorIdentifier")!.GetValue(declaration) + ); + Assert.Equal( + "Auth, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", + declaration.GetType().GetProperty("AssemblyIdentity")!.GetValue(declaration) + ); + } + Assert.Empty(Run(Mount(name: new string('a', 63))).GetRunResult().Diagnostics); + Assert.Empty(Run(Mount(name: "public")).GetRunResult().Diagnostics); + Reject(Mount(name: new string('a', 64)), "63 UTF-8 bytes"); + foreach (var name in new[] { "", "auth.data", "a-b", "1auth", " auth" }) + Reject(Mount(name: name), "database identifier"); + foreach (var name in new[] { "st", "ST", "spacetimedb", "pg_catalog", "PG_temp" }) + Reject(Mount(name: name), "reserved"); + foreach (var accessor in new[] { "", "a.b", "a-b", "1auth", "@class", " auth" }) + Reject(Mount(accessor: accessor), "C# identifier"); + Reject("[assembly: SpacetimeDB.Namespace(typeof(Auth.Marker))]", "C# identifier"); + Reject("[assembly: SpacetimeDB.Namespace(null)]", "marker type"); + Reject(Mount("LocalMarker") + "public class LocalMarker { }", "cannot mount itself"); + Reject(Mount("System.String"), "no discovered module descriptor"); + Reject(Mount() + Mount(accessor: "Other", name: "other"), "only be mounted once"); + Reject(Mount() + Mount("Audit.Marker", "Audit", "AUTH_DATA"), "case-insensitive"); + Reject(Mount() + Mount("Audit.Marker", "MyAuth", "audit_data"), "accessor 'MyAuth'"); + Reject(Mount() + "[SpacetimeDB.Table(Accessor = \"MyAuth\")] public partial struct Row { public uint Id; }", + "root table accessor"); + + var oldLanguage = fixture.ParseOptions.WithLanguageVersion(LanguageVersion.CSharp13); + var oldCompilation = Create("Consumer", "", auth, audit).RemoveAllSyntaxTrees() + .AddSyntaxTrees(CSharpSyntaxTree.ParseText(usings + Mount(), oldLanguage)); + var oldResult = CSharpGeneratorDriver.Create( + [new Module().AsSourceGenerator()], parseOptions: oldLanguage + ).RunGenerators(oldCompilation).GetRunResult(); + Assert.Contains(oldResult.Diagnostics, d => d.GetMessage().Contains("require .NET 10 and C# 14")); + + // Only assembly targets are legal, independently of generator validation. + var wrongTarget = Create("Consumer", "[SpacetimeDB.Namespace(typeof(Auth.Marker))] public class Wrong { }", auth); + Assert.Contains(wrongTarget.GetDiagnostics(), d => d.Id == "CS0592"); + + var original = Run(Mount()); + foreach (var source in new[] { Mount(name: "other_data"), Mount(accessor: "Other") }) + { + var changed = original.RunGenerators(Create("Consumer", source, auth, audit)); + Assert.Empty(changed.GetRunResult().Diagnostics); + Assert.NotEqual(Assert.Single(Parsed(original)), Assert.Single(Parsed(changed))); + Assert.Contains( + changed.GetRunResult().Results.Single().TrackedSteps["SpacetimeDB.Namespace.Parse"] + .SelectMany(s => s.Outputs), + o => o.Reason == IncrementalStepRunReason.Modified + ); + } +#else + var compilation = Create("Consumer", Mount(), auth, audit); + Assert.Null(compilation.GetTypeByMetadataName("SpacetimeDB.NamespaceAttribute")); + Assert.Contains(compilation.GetDiagnostics(), d => d.Id == "CS0234"); + Assert.Empty(Run(Mount()).GetRunResult().Diagnostics); +#endif + } + [Fact] public static async Task TypeGeneratorOnClient() { @@ -294,9 +443,11 @@ public static async Task TypeGeneratorOnClient() #if NET10_0_OR_GREATER [Theory] - [InlineData(false)] - [InlineData(true)] - public static async Task NamespaceDependenciesRegisterOnceInStableOrder(bool rootHasTable) + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(true, true)] + public static async Task NamespaceDependenciesRegisterOnceInStableOrder(bool rootHasTable, bool mounted) { var fixture = await Fixture.Compile("server", "net10.0"); const string usings = "global using System; global using System.IO; " @@ -355,24 +506,65 @@ MethodDeclarationSyntax Method(CSharpCompilation compilation, string name) => As var utility = Emit(Create("Utility", "public class UtilityLink { public Shared.Sentinel Value; }", shared)); var rootSource = rootHasTable ? Table("Root") : ""; + if (mounted) + rootSource = "[assembly: SpacetimeDB.Namespace(typeof(Alpha.Sentinel), Accessor = \"Auth\", Name = \"auth_data\")]\n" + + "[assembly: SpacetimeDB.Namespace(typeof(Beta.Sentinel), Accessor = \"class\", Name = \"audit_data\")]\n" + + rootSource + + "public static class Helpers { public static ulong Count(SpacetimeDB.ReducerContext ctx) => ctx.Db.Auth.AlphaRow.Count + ctx.Db.@class.BetaRow.Count + ctx.Db.SharedRow.Count; }"; var root = Generate(Create("Root", rootSource, beta, utility, shared, alpha)); var reordered = Generate(Create("Root", rootSource, alpha, shared, utility, beta)); Emit(root); Emit(reordered); string[] Calls(CSharpCompilation compilation) => - [.. Method(compilation, "Main").DescendantNodes() + [.. Method(compilation, "Initialize").DescendantNodes() .OfType() - .Select(call => call.Expression.ToString())]; - var expected = new[] + .Select(call => call.Expression.ToString()) + .Where(call => call.EndsWith(".Register"))]; + CSharpCompilation[] orderedDependencies = mounted + ? [sharedCompilation, alphaCompilation, betaCompilation] + : [alphaCompilation, betaCompilation, sharedCompilation]; + var expected = new[] { Descriptor(root) + ".Register" } + .Concat(orderedDependencies.Select(c => Descriptor(c) + ".Register")).ToArray(); + if (mounted) { - Descriptor(root) + ".Register", - Descriptor(alphaCompilation) + ".Register", - Descriptor(betaCompilation) + ".Register", - Descriptor(sharedCompilation) + ".Register", - }; + var init = Method(root, "Initialize"); + var submodules = init.DescendantNodes().OfType() + .Where(call => call.Expression.ToString().EndsWith(".RegisterSubmodule")).ToArray(); + Assert.Equal(["\"auth_data\"", "\"audit_data\""], + submodules.Select(call => call.ArgumentList.Arguments[0].ToString())); + var invalid = root.AddSyntaxTrees(CSharpSyntaxTree.ParseText( + "public static class BadView { public static void Write(SpacetimeDB.ViewContext ctx) => ctx.Db.Auth.AlphaRow.Insert(new Alpha.AlphaRow()); }", + fixture.ParseOptions)); + Assert.Contains(GetCompilationErrors(invalid), d => d.Id == "CS1061"); + } Assert.Equal(expected, Calls(root)); Assert.Equal(expected, Calls(reordered)); + foreach (var (export, category) in new[] + { + ("__call_reducer__", "Reducer"), + ("__call_procedure__", "Procedure"), + ("__call_http_handler__", "HttpHandler"), + ("__call_view__", "View"), + ("__call_view_anon__", "AnonymousView"), + }) + { + var body = Method(root, export).Body!; + var routes = body.DescendantNodes().OfType() + .Where(call => call.Expression is MemberAccessExpressionSyntax member + && member.Name.Identifier.ValueText == "CallLocal" + category).ToArray(); + Assert.Equal(expected.Select(name => name.Replace(".Register", ".CallLocal" + category)), + routes.Select(call => call.Expression.ToString())); + Assert.All(routes, call => Assert.Equal("localId", + call.ArgumentList.Arguments[0].Expression.ToString())); + var offsets = body.DescendantNodes().OfType() + .Where(assignment => assignment.IsKind(SyntaxKind.SubtractAssignmentExpression)); + Assert.Equal(expected.Select(name => name.Replace(".Register", "." + category + "Count")), + offsets.Select(assignment => assignment.Right.ToString())); + var negativeGuard = Assert.IsType(body.Statements[0]); + Assert.Equal("id < 0", negativeGuard.Condition.ToString()); + Assert.Equal(Method(root, export).ToString(), Method(reordered, export).ToString()); + } Assert.DoesNotContain(Method(root, "Register").DescendantNodes() .OfType(), call => call.Expression.ToString().Contains("AssemblyDescriptor.Register")); @@ -381,6 +573,39 @@ [.. Method(compilation, "Main").DescendantNodes() var plainUtility = Emit(Create("PlainUtility", "public class PlainUtility { }")); var empty = Generate(Create("Empty", "", plainUtility)); Assert.Empty(empty.GetSymbolsWithName("AssemblyDescriptor", SymbolFilter.Type)); + + var nested = Emit(Generate(Create("Nested", + "[assembly: SpacetimeDB.Namespace(typeof(Alpha.Sentinel), Accessor = \"Auth\", Name = \"auth_data\")]", + alpha, shared))); + var nestedResult = CSharpGeneratorDriver.Create( + [new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions + ).RunGenerators(Create("Outer", "", nested, alpha, shared)).GetRunResult(); + Assert.Contains(nestedResult.Diagnostics, diagnostic => + diagnostic.GetMessage().Contains("Only the consuming root")); + + foreach (var kind in new[] { "Init", "ClientConnected", "ClientDisconnected" }) + { + var lifecycle = Emit(Generate(Create("LifecycleDependency", $$""" + public class Marker { } + public static partial class LifecycleFunctions { + [SpacetimeDB.Reducer(SpacetimeDB.ReducerKind.{{kind}})] + public static void Handle(SpacetimeDB.ReducerContext ctx) { } + } + """))); + var lifecycleResult = CSharpGeneratorDriver.Create( + [new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions + ).RunGenerators(Create("LifecycleConsumer", + "[assembly: SpacetimeDB.Namespace(typeof(Marker), Accessor = \"Auth\", Name = \"auth_data\")]", + lifecycle)).GetRunResult(); + Assert.Contains(lifecycleResult.Diagnostics, diagnostic => + diagnostic.GetMessage().Contains("LifecycleFunctions.Handle (" + kind + ")") + && diagnostic.GetMessage().Contains("auth_data")); + // The same dependency can still be published alone or merged into the root scope. + Generate(Create("FlatLifecycleConsumer", "", lifecycle)); + Generate(Create("PublicLifecycleConsumer", + "[assembly: SpacetimeDB.Namespace(typeof(Marker), Accessor = \"Auth\", Name = \"public\")]", + lifecycle)); + } } [Fact] @@ -422,6 +647,38 @@ public static async Task NamespaceDescriptorCrossAssemblyRegistration() moduleAssembly, descriptor.ContainingAssembly )); var descriptorName = descriptor.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + var dispatchCalls = new List(); + foreach (var category in new[] { "Reducer", "Procedure", "HttpHandler", "View", "AnonymousView" }) + { + var methodName = "CallLocal" + category; + var method = Assert.IsAssignableFrom( + Assert.Single(descriptor.GetMembers(methodName)) + ); + Assert.Equal(Accessibility.Public, method.DeclaredAccessibility); + Assert.True(method.IsStatic); + Assert.DoesNotContain(method.GetAttributes(), attribute => + attribute.AttributeClass?.Name == "UnmanagedCallersOnlyAttribute"); + var count = Assert.IsAssignableFrom( + Assert.Single(descriptor.GetMembers(category + "Count")) + ); + Assert.True(count.IsConst); + Assert.Equal(Accessibility.Public, count.DeclaredAccessibility); + var localMethod = Assert.Single(compilation.SyntaxTrees + .SelectMany(tree => tree.GetRoot().DescendantNodes()) + .OfType() + .Where(method => method.Identifier.ValueText == methodName + && method.Parent is ClassDeclarationSyntax type + && type.Identifier.ValueText == "ModuleRegistration")); + var localSwitch = Assert.IsType(localMethod.ExpressionBody!.Expression); + Assert.Equal(localSwitch.Arms.Count - 1, Assert.IsType(count.ConstantValue)); + + var parameters = string.Join(", ", method.Parameters.Select(parameter => + parameter.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + + " " + parameter.Name)); + var arguments = string.Join(", ", method.Parameters.Select(parameter => parameter.Name)); + dispatchCalls.Add($"public static global::SpacetimeDB.Internal.Errno {methodName}({parameters})" + + $" => {descriptorName}.{methodName}({arguments});"); + } var consumerSource = $$""" using System.IO; @@ -431,6 +688,8 @@ public static async Task NamespaceDescriptorCrossAssemblyRegistration() public static class DescriptorConsumer { + {{string.Join("\n", dispatchCalls)}} + public static void Register(ModuleBuilder builder) => {{descriptorName}}.Register(builder); @@ -456,6 +715,37 @@ public static string[] ReducerNames(ModuleBuilder builder) => Describe(builder).Sections.OfType() .SelectMany(section => section.Reducers_) .Select(reducer => reducer.SourceName).ToArray(); + + public static bool CheckNamespaces() + { + const string first = "Library, Version=1.0.0.0"; + const string second = "Library, Version=2.0.0.0"; + var placements = new System.Collections.Generic.Dictionary + { + [first] = "auth_data", + [second] = "audit_data", + ["merged"] = "public", + }; + var registry = new NamespaceRegistry("root", placements); + placements[first] = "changed"; + if (registry.Resolve(first, "User") != "auth_data.User" + || registry.Resolve(second, "User") != "audit_data.User" + || registry.Resolve("root", "User") != "User" + || registry.Resolve("unmounted", "User") != "User" + || registry.Resolve("merged", "User") != "User") + return false; + try { SpacetimeDB.Internal.Module.ResolveName(first, "User"); return false; } + catch (System.InvalidOperationException) { } + SpacetimeDB.Internal.Module.InstallNamespaces(registry); + if (SpacetimeDB.Internal.Module.ResolveName(first, "User") != "auth_data.User") return false; + try { SpacetimeDB.Internal.Module.InstallNamespaces(registry); return false; } + catch (System.InvalidOperationException) { } + try { new NamespaceRegistry(first, placements); return false; } + catch (System.ArgumentException) { } + try { new NamespaceRegistry("root", placements.Concat(placements)); return false; } + catch (System.ArgumentException) { } + return true; + } } """; consumer = consumer.AddSyntaxTrees( @@ -527,6 +817,8 @@ byte[] Snapshot(object builder) => (byte[])consumerType.GetMethod("Snapshot")! Assert.Equal(registered, Snapshot(second)); Assert.Equal(registered, Snapshot(first)); Assert.Equal(rootBefore, Snapshot(root)); + + Assert.True((bool)consumerType.GetMethod("CheckNamespaces")!.Invoke(null, null)!); } finally { diff --git a/crates/bindings-csharp/Codegen/Diag.cs b/crates/bindings-csharp/Codegen/Diag.cs index c2374db5b8e..a81b02475f6 100644 --- a/crates/bindings-csharp/Codegen/Diag.cs +++ b/crates/bindings-csharp/Codegen/Diag.cs @@ -361,4 +361,35 @@ string type $"View '{ctx.method.Identifier}' declares primary key '{ctx.primaryKey}', but its type '{ctx.type}' is not supported for view primary keys.", ctx => ctx.primaryKeySyntax ); + public static readonly ErrorDescriptor<(AttributeData attribute, string message)> InvalidNamespace = + new( + group, + "Invalid namespace mount", + ctx => $"{ctx.message}", + ctx => ctx.attribute + ); + + public static readonly ErrorDescriptor<(string accessor, string first, string second)> NamespaceAccessorCollision = + new( + group, + "Conflicting module accessors", + ctx => $"Accessor '{ctx.accessor}' is contributed by both '{ctx.first}' and '{ctx.second}'. Mount the conflicting dependency with a distinct accessor.", + _ => Location.None + ); + + public static readonly ErrorDescriptor DependencyNamespaceMounts = + new( + group, + "Dependency declares namespace mounts", + identity => $"Dependency '{identity}' declares namespace mounts. Only the consuming root may choose dependency placement; move those declarations to the root.", + _ => Location.None + ); + + public static readonly ErrorDescriptor<(string assembly, string name, string reducers)> MountedLifecycleReducers = + new( + group, + "Mounted dependency declares lifecycle reducers", + ctx => $"Dependency '{ctx.assembly}' mounted in namespace '{ctx.name}' declares lifecycle reducers: {ctx.reducers}. Lifecycle reducers are only supported in the root scope; remove them or leave the dependency unmounted.", + _ => Location.None + ); } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index ddfc00b7e26..5d059815e4e 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -492,6 +492,16 @@ record TableDeclaration : BaseTypeDeclaration public readonly EquatableArray Indexes; private readonly bool isRowStruct; + private readonly string assemblyIdentity; + private readonly bool sharedContexts; + private readonly string handlesNamespace; + + private string TableHandlesNamespace => handlesNamespace + ".TableHandles"; + private string ViewHandlesNamespace => handlesNamespace + ".ViewHandles"; + + private string LookupName(string localName) => sharedContexts + ? $"global::SpacetimeDB.Internal.Module.ResolveName({SymbolDisplay.FormatLiteral(assemblyIdentity, true)}, {SymbolDisplay.FormatLiteral(localName, true)})" + : SymbolDisplay.FormatLiteral(localName, true); public int? GetColumnIndex(AttributeData attrContext, string name, DiagReporter diag) { @@ -511,6 +521,11 @@ public TableDeclaration(GeneratorAttributeSyntaxContext context, DiagReporter di { var typeSyntax = (TypeDeclarationSyntax)context.TargetNode; + var compilation = context.SemanticModel.Compilation; + assemblyIdentity = compilation.Assembly.Identity.ToString(); + sharedContexts = Module.UsesSharedContexts(compilation); + handlesNamespace = sharedContexts ? Module.AssemblyNamespace(compilation.Assembly) : "SpacetimeDB.Internal"; + isRowStruct = ((INamedTypeSymbol)context.TargetSymbol).IsValueType; if (Kind is TypeKind.Sum) @@ -566,7 +581,7 @@ public IEnumerable GenerateTableAccessorFilters(TableAccessor tableAcces var vis = SyntaxFacts.GetText(Visibility); var globalName = $"global::{FullName}"; - var uniqueIndexBase = isRowStruct ? "UniqueIndex" : "RefUniqueIndex"; + var uniqueIndexBase = "global::SpacetimeDB.Internal." + (isRowStruct ? "UniqueIndex" : "RefUniqueIndex"); foreach (var ct in GetConstraints(tableAccessor, ColumnAttrs.Unique)) { @@ -583,7 +598,7 @@ public IEnumerable GenerateTableAccessorFilters(TableAccessor tableAcces : ""; yield return $$""" {{vis}} sealed class {{f.Identifier}}UniqueIndex : {{uniqueIndexBase}}<{{tableAccessor.Identifier}}, {{globalName}}, {{f.Type.Name}}, {{f.Type.BSATNName}}> { - internal {{f.Identifier}}UniqueIndex() : base("{{standardIndexName}}") {} + internal {{f.Identifier}}UniqueIndex() : base({{LookupName(standardIndexName)}}) {} // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. @@ -610,7 +625,7 @@ public IEnumerable GenerateTableAccessorFilters(TableAccessor tableAcces var standardIndexName = index.StandardIndexName(tableAccessor); yield return $$""" - {{vis}} sealed class {{identifierName}}Index() : SpacetimeDB.Internal.IndexBase<{{globalName}}>("{{standardIndexName}}") { + {{vis}} sealed class {{identifierName}}Index() : SpacetimeDB.Internal.IndexBase<{{globalName}}>({{LookupName(standardIndexName)}}) { """; for (var n = 0; n < members.Length; n++) @@ -679,12 +694,12 @@ private IEnumerable GenerateReadOnlyAccessorFilters(TableAccessor tableA yield return $$$""" public sealed class {{{f.Identifier}}}Index : {{{uniqueIndexBase}}}< - global::SpacetimeDB.Internal.ViewHandles.{{{tableAccessor.Identifier}}}ReadOnly, + global::{{{ViewHandlesNamespace}}}.{{{tableAccessor.Identifier}}}ReadOnly, {{{globalName}}}, {{{f.Type.Name}}}, {{{f.Type.BSATNName}}}> { - internal {{{f.Identifier}}}Index() : base("{{{standardIndexName}}}") { } + internal {{{f.Identifier}}}Index() : base({{{LookupName(standardIndexName)}}}) { } public {{{globalName}}}? Find({{{f.Type.Name}}} key) => FindSingle(key); } @@ -711,7 +726,7 @@ public sealed class {{{f.Identifier}}}Index public sealed class {{{identifierName}}}Index : global::SpacetimeDB.Internal.ReadOnlyIndexBase<{{{globalName}}}> { - internal {{{identifierName}}}Index() : base("{{{standardIndexName}}}") {} + internal {{{identifierName}}}Index() : base({{{LookupName(standardIndexName)}}}) {} """, }; @@ -801,6 +816,7 @@ public IEnumerable GenerateTableAccessors() globalName, $$$""" {{{SyntaxFacts.GetText(Visibility)}}} readonly struct {{{accessorIdentifier}}} : {{{iTable}}} { + {{{(sharedContexts ? $"public static string LookupName => {LookupName(v.Name)};" : "")}}} public static {{{globalName}}} ReadGenFields(System.IO.BinaryReader reader, {{{globalName}}} row) { {{{string.Join( "\n", @@ -858,7 +874,7 @@ v.Scheduled is { } scheduled {{{string.Join("\n", GenerateTableAccessorFilters(v))}}} } """, - $"{SyntaxFacts.GetText(Visibility)} global::SpacetimeDB.Internal.TableHandles.{accessorIdentifier} {accessorIdentifier} => new();" + $"{SyntaxFacts.GetText(Visibility)} global::{TableHandlesNamespace}.{accessorIdentifier} {accessorIdentifier} => new();" ); } } @@ -891,7 +907,7 @@ public IEnumerable GenerateReadOnlyAccessors() {{{visibility}}} sealed class {{{accessorIdentifier}}}ReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView<{{{globalName}}}> { - internal {{{accessorIdentifier}}}ReadOnly() : base("{{{accessor.Name}}}") { } + internal {{{accessorIdentifier}}}ReadOnly() : base({{{LookupName(accessor.Name)}}}) { } /// /// Returns the number of rows in this table. @@ -904,7 +920,7 @@ public IEnumerable GenerateReadOnlyAccessors() {{{readOnlyIndexDecls}}} } """, - $"{visibility} global::SpacetimeDB.Internal.ViewHandles.{accessorIdentifier}ReadOnly {accessorIdentifier} => new();" + $"{visibility} global::{ViewHandlesNamespace}.{accessorIdentifier}ReadOnly {accessorIdentifier} => new();" ); } } @@ -944,8 +960,8 @@ string ColInit(ColumnDeclaration col) return $"{col.Identifier} = new {colType}<{globalRowName}, {valueTypeName}>(tableName, \"{col.Name}\");"; } - var colsDecls = string.Join("\n ", Members.Select(ColDecl)); - var colsInits = string.Join("\n ", Members.Select(ColInit)); + var colsDecls = string.Join("\n ", Members.Select(ColDecl)); + var colsInits = string.Join("\n ", Members.Select(ColInit)); var ixPositions = new global::System.Collections.Generic.HashSet(); foreach (var c in GetConstraints(accessor, ColumnAttrs.PrimaryKey | ColumnAttrs.Unique)) @@ -989,8 +1005,8 @@ string IxColInit(ColumnDeclaration col) return $"{col.Identifier} = new {colType}<{globalRowName}, {valueTypeName}>(tableName, \"{col.Name}\");"; } - var ixColsDecls = string.Join("\n ", ixMembers.Select(IxColDecl)); - var ixColsInits = string.Join("\n ", ixMembers.Select(IxColInit)); + var ixColsDecls = string.Join("\n ", ixMembers.Select(IxColDecl)); + var ixColsInits = string.Join("\n ", ixMembers.Select(IxColInit)); yield return $$""" {{vis}} readonly struct {{colsTypeName}} @@ -1015,8 +1031,8 @@ string IxColInit(ColumnDeclaration col) {{(useExtensions ? "public static partial class QueryTableExtensions" : "public readonly partial struct QueryBuilder")}} { - {{(useExtensions ? " extension(global::SpacetimeDB.QueryBuilder from) {\n" : "")}} {{vis}} global::SpacetimeDB.Table<{{globalRowName}}, {{colsTypeName}}, {{ixColsTypeName}}> {{accessorIdentifier}}() => - new("{{tableName}}", new {{colsTypeName}}("{{tableName}}"), new {{ixColsTypeName}}("{{tableName}}")); + {{(useExtensions ? " extension(global::SpacetimeDB.QueryBuilder from) {\n " : " ")}}{{vis}} global::SpacetimeDB.Table<{{globalRowName}}, {{colsTypeName}}, {{ixColsTypeName}}> {{accessorIdentifier}}() => + {{(useExtensions ? " " : " ")}}new("{{tableName}}", new {{colsTypeName}}("{{tableName}}"), new {{ixColsTypeName}}("{{tableName}}")); {{(useExtensions ? " }\n" : "")}}} """; } @@ -1506,6 +1522,7 @@ public static byte[] Invoke( /// record ReducerDeclaration { + private readonly string? declaringAssembly; public readonly string Name; public readonly string? CanonicalName; public readonly ReducerKind Kind; @@ -1518,6 +1535,8 @@ record ReducerDeclaration public ReducerDeclaration(GeneratorAttributeSyntaxContext context, DiagReporter diag) { + declaringAssembly = Module.UsesSharedContexts(context.SemanticModel.Compilation) + ? context.SemanticModel.Compilation.Assembly.Identity.ToString() : null; var methodSyntax = (MethodDeclarationSyntax)context.TargetNode; var method = (IMethodSymbol)context.TargetSymbol; var attr = context.Attributes.Single().ParseAs(); @@ -1616,7 +1635,7 @@ public Scope.Extensions GenerateSchedule() "\n", Args.Select(a => $"new {a.Type.ToBSATNString()}().Write(writer, {a.Identifier});") )}} - SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate(nameof({{Identifier}}), stream); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate({{(declaringAssembly is null ? $"nameof({Identifier})" : $"global::SpacetimeDB.Internal.Module.ResolveName({SymbolDisplay.FormatLiteral(declaringAssembly, true)}, nameof({Identifier}))")}}, stream); } """ ); @@ -1630,6 +1649,7 @@ public Scope.Extensions GenerateSchedule() /// record ProcedureDeclaration { + private readonly string? declaringAssembly; public readonly string Name; public readonly string? CanonicalName; public readonly string FullName; @@ -1645,6 +1665,8 @@ record ProcedureDeclaration public ProcedureDeclaration(GeneratorAttributeSyntaxContext context, DiagReporter diag) { + declaringAssembly = Module.UsesSharedContexts(context.SemanticModel.Compilation) + ? context.SemanticModel.Compilation.Assembly.Identity.ToString() : null; var methodSyntax = (MethodDeclarationSyntax)context.TargetNode; var method = (IMethodSymbol)context.TargetSymbol; var attr = context.Attributes.Single().ParseAs(); @@ -1837,7 +1859,7 @@ public Scope.Extensions GenerateSchedule() "\n", Args.Select(a => $"new {a.Type.ToBSATNString()}().Write(writer, {a.Identifier});") )}} - SpacetimeDB.Internal.ProcedureExtensions.VolatileNonatomicScheduleImmediate(nameof({{Identifier}}), stream); + SpacetimeDB.Internal.ProcedureExtensions.VolatileNonatomicScheduleImmediate({{(declaringAssembly is null ? $"nameof({Identifier})" : $"global::SpacetimeDB.Internal.Module.ResolveName({SymbolDisplay.FormatLiteral(declaringAssembly, true)}, nameof({Identifier}))")}}, stream); } """ ); @@ -2018,11 +2040,31 @@ DiagReporter diag } } -record AssemblyDeclaration(string Identity, string DescriptorTypeName); +record AssemblyTableAccessor(string Name, string TypeName); + +record AssemblyDeclaration( + string Identity, + string DescriptorTypeName, + bool DeclaresMounts, + string LifecycleReducers, + EquatableArray Tables, + EquatableArray ReadOnlyTables +); [Generator] public class Module : IIncrementalGenerator { + internal static bool UsesSharedContexts(Compilation compilation) => + compilation.SyntaxTrees.Any(tree => tree.Options is CSharpParseOptions options + && options.PreprocessorSymbolNames.Contains("NET10_0_OR_GREATER")); + + internal static string AssemblyNamespace(IAssemblySymbol assembly) => + "SpacetimeDB.Generated.Assembly_" + + string.Concat(assembly.Identity.ToString().Select(c => ((int)c).ToString("X4"))); + + private static string IndentGeneratedCode(string code, int spaces) => + code.Replace("\n", "\n" + new string(' ', spaces)); + private static EquatableArray DiscoverAssemblies( Compilation compilation, CancellationToken cancellationToken @@ -2082,9 +2124,25 @@ marker is null assemblies.Add( new AssemblyDeclaration( assembly.Identity.ToString(), - descriptor.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + descriptor.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat), + assembly.GetAttributes().Any(attribute => + attribute.AttributeClass?.ToDisplayString() == "SpacetimeDB.NamespaceAttribute"), + descriptor.GetMembers("LifecycleReducers").OfType() + .FirstOrDefault()?.ConstantValue as string ?? "", + ReadAccessors("Tables"), + ReadAccessors("ReadOnlyTables") ) ); + + EquatableArray ReadAccessors(string container) => new( + descriptor.GetTypeMembers(container).SelectMany(type => type.GetMembers()) + .OfType() + .Where(property => property.DeclaredAccessibility == Accessibility.Public) + .Select(property => new AssemblyTableAccessor( + property.Name, + property.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + )).ToImmutableArray() + ); } return new( @@ -2351,7 +2409,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) "Reducer", context, reducers - .Select((r, ct) => (r.Name, r.FullName, r.CanonicalName, Class: r.GenerateClass())) + .Select((r, ct) => (r.Name, r.FullName, r.CanonicalName, r.Kind, Class: r.GenerateClass())) .WithTrackingName("SpacetimeDB.Reducer.GenerateClass"), r => r.Name, r => r.FullName @@ -2481,23 +2539,69 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Select((tuple, ct) => FlattenModuleOutputInputs(tuple)); var extensionNamespace = context.CompilationProvider.Select( - (compilation, _) => - "SpacetimeDB.Generated.Assembly_" - + string.Concat( - compilation.Assembly.Identity.ToString() - .Select(c => ((int)c).ToString("X4")) - ) + (compilation, _) => ( + Name: AssemblyNamespace(compilation.Assembly), + Identity: compilation.Assembly.Identity.ToString(), + SharedContexts: UsesSharedContexts(compilation) + ) ); var referencedAssemblies = context.CompilationProvider.Select(DiscoverAssemblies); + var namespaceDeclarations = context.CompilationProvider + .Combine(referencedAssemblies) + .Combine(tableDecls) + .SelectMany((input, ct) => new[] + { + DiagReporter.With(Location.None, diag => NamespaceDeclaration.Parse( + input.Left.Left, + input.Left.Right, + input.Right.SelectMany(t => t.TableAccessors.Select(a => a.Name)), + diag, + ct + )) + }) + .ReportDiagnostics(context) + .WithTrackingName("SpacetimeDB.Namespace.Parse") + .Collect(); // Register the generated source code with the compilation context as part of module publishing // Once the compilation is complete, the generated code will be used to create tables and reducers in the database context.RegisterSourceOutput( - moduleOutputInputs.Combine(extensionNamespace).Combine(referencedAssemblies), + moduleOutputInputs.Combine(extensionNamespace).Combine(referencedAssemblies) + .Combine(namespaceDeclarations), (context, input) => { - var ((inputs, extensionNamespaceName), assemblies) = input; + var (((inputs, assemblyContext), assemblies), mounts) = input; + var extensionNamespaceName = assemblyContext.Name; + var handlesNamespace = assemblyContext.SharedContexts + ? extensionNamespaceName : "SpacetimeDB.Internal"; + var mountByIdentity = mounts.SelectMany(m => m) + .ToDictionary(m => m.AssemblyIdentity, StringComparer.Ordinal); + bool IsChild(AssemblyDeclaration assembly) => + mountByIdentity.TryGetValue(assembly.Identity, out var mount) + && !mount.Name.Equals("public", StringComparison.OrdinalIgnoreCase); + var unmountedAssemblies = assemblies.Where(a => !IsChild(a)).ToArray(); + var mountedAssemblies = assemblies.Where(IsChild).ToArray(); + var registrationOrder = unmountedAssemblies.Concat(mountedAssemblies).ToArray(); + foreach (var assembly in assemblies.Where(a => a.DeclaresMounts)) + context.ReportDiagnostic(ErrorDescriptor.DependencyNamespaceMounts.ToDiag(assembly.Identity)); + foreach (var assembly in mountedAssemblies.Where(a => a.LifecycleReducers.Length != 0)) + context.ReportDiagnostic(ErrorDescriptor.MountedLifecycleReducers.ToDiag( + (assembly.Identity, mountByIdentity[assembly.Identity].Name, assembly.LifecycleReducers))); + + string GenerateDispatchRouting(string category, string arguments, string unknownId) + { + // Match Main's registration order; each category has its own local IDs. + var descriptors = new[] { $"global::{extensionNamespaceName}.AssemblyDescriptor" } + .Concat(registrationOrder.Select(assembly => assembly.DescriptorTypeName)); + var routes = descriptors.Select(descriptor => $$""" + if ((uint)localId < (uint){{descriptor}}.{{category}}Count) + return {{descriptor}}.CallLocal{{category}}(localId, {{arguments}}); + localId -= {{descriptor}}.{{category}}Count; + """); + return $"if (id < 0) {{ {unknownId} }}\nvar localId = id;\n" + + string.Join("\n", routes) + "\n" + unknownId; + } var ( tableAccessors, @@ -2513,6 +2617,62 @@ public void Initialize(IncrementalGeneratorInitializationContext context) columnDefaultValues ) = inputs; + string ConsumerAccessors(bool readOnly) + { + var members = new List(); + var used = new Dictionary(StringComparer.Ordinal); + foreach (var table in tableAccessors) + used[table.TableAccessorName] = assemblyContext.Identity; + void Add(string name, string owner, string declaration) + { + if (used.TryGetValue(name, out var previous)) + { + if (!readOnly) + context.ReportDiagnostic(ErrorDescriptor.NamespaceAccessorCollision.ToDiag( + (name, previous, owner))); + return; + } + used.Add(name, owner); + members.Add(declaration); + } + foreach (var assembly in assemblies) + { + if (mountByIdentity.TryGetValue(assembly.Identity, out var mount)) + { + var container = readOnly ? "ReadOnlyTables" : "Tables"; + Add(mount.Accessor, assembly.Identity, + $"public {assembly.DescriptorTypeName}.{container} {mount.AccessorIdentifier} => new();"); + } + else + { + foreach (var table in readOnly ? assembly.ReadOnlyTables : assembly.Tables) + Add(table.Name, assembly.Identity, + $"public {table.TypeName} {EscapeIdentifier(table.Name)} => new {assembly.DescriptorTypeName}.{(readOnly ? "ReadOnlyTables" : "Tables")}().{EscapeIdentifier(table.Name)};"); + } + } + return string.Join("\n", members); + } + var consumerWritableAccessors = ConsumerAccessors(false); + var consumerReadOnlyAccessors = ConsumerAccessors(true); + + var compositionRegistration = new List + { + "global::SpacetimeDB.Internal.Module.InstallNamespaces(new global::SpacetimeDB.Internal.NamespaceRegistry(" + + SymbolDisplay.FormatLiteral(assemblyContext.Identity, true) + ", new global::System.Collections.Generic.KeyValuePair[] {" + + string.Join(",", mountByIdentity.Values.Select(m => + $"new({SymbolDisplay.FormatLiteral(m.AssemblyIdentity, true)}, {SymbolDisplay.FormatLiteral(m.Name, true)})")) + "}));", + $"global::{extensionNamespaceName}.AssemblyDescriptor.Register(global::SpacetimeDB.Internal.Module.RootBuilder);" + }; + foreach (var assembly in unmountedAssemblies) + compositionRegistration.Add($"{assembly.DescriptorTypeName}.Register(global::SpacetimeDB.Internal.Module.RootBuilder);"); + for (var i = 0; i < mountedAssemblies.Length; i++) + { + var assembly = mountedAssemblies[i]; + compositionRegistration.Add($"var child{i} = new global::SpacetimeDB.Internal.ModuleBuilder();"); + compositionRegistration.Add($"{assembly.DescriptorTypeName}.Register(child{i}, global::SpacetimeDB.Internal.Module.RootBuilder);"); + compositionRegistration.Add($"global::SpacetimeDB.Internal.Module.RootBuilder.RegisterSubmodule({SymbolDisplay.FormatLiteral(mountByIdentity[assembly.Identity].Name, true)}, child{i});"); + } + if (settings.Array.Length > 1) { context.ReportDiagnostic( @@ -2593,12 +2753,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Where(s => !string.IsNullOrWhiteSpace(s)) .ToArray(); - var preRegistrations = - preRegistrationLines.Length == 0 - ? string.Empty - : "\n " - + string.Join("\n ", preRegistrationLines) - + "\n"; + var preRegistrations = string.Join("\n", preRegistrationLines); var queryBuilderMembers = string.Join( "\n", @@ -2649,12 +2804,12 @@ public void Initialize(IncrementalGeneratorInitializationContext context) namespace SpacetimeDB { #if !NET10_0_OR_GREATER - {{queryBuilderMembers}} + {{IndentGeneratedCode(queryBuilderMembers, 4)}} #endif public static class Handlers { - {{string.Join("\n", addHttpHandlers.Select(r => + {{IndentGeneratedCode(string.Join("\n", addHttpHandlers.Select(r => $"public static readonly global::SpacetimeDB.Handler {EscapeIdentifier(r.Name)} = new(nameof({r.FullName}));" - ))}} + )), 8)}} } #if !NET10_0_OR_GREATER @@ -2854,7 +3009,7 @@ internal HandlerTxContext(Internal.TxContext inner) : base(inner) {} } public sealed class Local : global::SpacetimeDB.LocalBase { - {{string.Join("\n", tableAccessors.Select(v => v.Getter))}} + {{IndentGeneratedCode(string.Join("\n", tableAccessors.Select(v => v.Getter)), 8)}} } public sealed record ViewContext : DbContext, Internal.IViewContext @@ -2885,45 +3040,124 @@ internal AnonymousViewContext(Internal.LocalReadOnly db) #if NET10_0_OR_GREATER namespace {{extensionNamespaceName}} { public static class AssemblyDescriptor { + public const string LifecycleReducers = {{SymbolDisplay.FormatLiteral(string.Join(", ", addReducers.Where(r => r.Kind != ReducerKind.UserDefined).Select(r => $"{r.FullName} ({r.Kind})")), true)}}; + public const int ReducerCount = {{addReducers.Array.Length}}; + public const int ProcedureCount = {{addProcedures.Array.Length}}; + public const int HttpHandlerCount = {{addHttpHandlers.Array.Length}}; + public const int ViewCount = {{views.Array.Count(v => !v.IsAnonymous)}}; + public const int AnonymousViewCount = {{views.Array.Count(v => v.IsAnonymous)}}; + + public static global::SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink error + ) => global::ModuleRegistration.CallLocalReducer( + id, sender_0, sender_1, sender_2, sender_3, conn_id_0, conn_id_1, timestamp, args, error + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink result_sink + ) => global::ModuleRegistration.CallLocalProcedure( + id, sender_0, sender_1, sender_2, sender_3, conn_id_0, conn_id_1, timestamp, args, result_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource request, + global::SpacetimeDB.Internal.BytesSource request_body, + global::SpacetimeDB.Internal.BytesSink response_sink, + global::SpacetimeDB.Internal.BytesSink response_body_sink + ) => global::ModuleRegistration.CallLocalHttpHandler( + id, timestamp, request, request_body, response_sink, response_body_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => global::ModuleRegistration.CallLocalView( + id, sender_0, sender_1, sender_2, sender_3, args, sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => global::ModuleRegistration.CallLocalAnonymousView( + id, args, sink + ); + public static void Register( - global::SpacetimeDB.Internal.ModuleBuilder builder) - => global::ModuleRegistration.Register(builder); + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null) + => global::ModuleRegistration.Register(builder, httpBuilder); + + public readonly struct Tables { + {{IndentGeneratedCode(string.Join("\n", tableAccessors.Select(v => v.Getter)), 12)}} + } + + public readonly struct ReadOnlyTables { + {{IndentGeneratedCode(string.Join("\n", readOnlyAccessors.Select(v => v.ReadOnlyGetter)), 12)}} + } } public static class LocalTableExtensions { extension(global::SpacetimeDB.Local db) { - {{string.Join("\n", tableAccessors.Select(v => v.Getter))}} + {{IndentGeneratedCode(string.Join("\n", tableAccessors.Select(v => v.Getter)), 12)}} + {{IndentGeneratedCode(consumerWritableAccessors, 12)}} } } public static class ReadOnlyTableExtensions { extension(global::SpacetimeDB.Internal.LocalReadOnly db) { - {{string.Join("\n", readOnlyAccessors.Select(v => v.ReadOnlyGetter))}} + {{IndentGeneratedCode(string.Join("\n", readOnlyAccessors.Select(v => v.ReadOnlyGetter)), 12)}} + {{IndentGeneratedCode(consumerReadOnlyAccessors, 12)}} } } - {{queryBuilderExtensionMembers}} + {{IndentGeneratedCode(queryBuilderExtensionMembers, 4)}} } #endif - namespace SpacetimeDB.Internal.TableHandles { - {{string.Join("\n", tableAccessors.Select(v => v.TableAccessor))}} + namespace {{handlesNamespace}}.TableHandles { + {{IndentGeneratedCode(string.Join("\n", tableAccessors.Select(v => v.TableAccessor)), 4)}} } - {{string.Join("\n", + {{IndentGeneratedCode(string.Join("\n", views.Array.Where(v => !v.IsAnonymous) .Select((v, i) => v.GenerateDispatcherClass((uint)i)) .Concat( views.Array.Where(v => v.IsAnonymous) .Select((v, i) => v.GenerateDispatcherClass((uint)i)) ) - )}} + ), 0)}} - namespace SpacetimeDB.Internal.ViewHandles { - {{string.Join("\n", readOnlyAccessors.Array.Select(v => v.ReadOnlyAccessor))}} + namespace {{handlesNamespace}}.ViewHandles { + {{IndentGeneratedCode(string.Join("\n", readOnlyAccessors.Array.Select(v => v.ReadOnlyAccessor)), 4)}} } #if !NET10_0_OR_GREATER namespace SpacetimeDB.Internal { public sealed partial class LocalReadOnly { - {{string.Join("\n", readOnlyAccessors.Select(v => v.ReadOnlyGetter))}} + {{IndentGeneratedCode(string.Join("\n", readOnlyAccessors.Select(v => v.ReadOnlyGetter)), 8)}} } } #endif @@ -2938,11 +3172,11 @@ static class ModuleRegistration { private static byte[] viewArgsBuffer = new byte[0x10_000]; private static byte[] anonymousViewArgsBuffer = new byte[0x10_000]; - {{string.Join("\n", addReducers.Select(r => r.Class))}} + {{IndentGeneratedCode(string.Join("\n", addReducers.Select(r => r.Class)), 4)}} - {{string.Join("\n", addProcedures.Select(r => r.Class))}} + {{IndentGeneratedCode(string.Join("\n", addProcedures.Select(r => r.Class)), 4)}} - {{string.Join("\n", addHttpHandlers.Select(r => r.Class))}} + {{IndentGeneratedCode(string.Join("\n", addHttpHandlers.Select(r => r.Class)), 4)}} public static List ToListOrEmpty(T? value) where T : struct => value is null ? new List() : new List { value.Value }; @@ -2958,7 +3192,9 @@ public static List ToListOrEmpty(T? value) where T : class // Prevent trimming of FFI exports that are invoked from C and not visible to C# trimmer. [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, typeof(ModuleRegistration))] #endif - public static void Main() { + public static void Main() => Initialize(); + + internal static void Initialize() { #if !NET10_0_OR_GREATER SpacetimeDB.Internal.Module.SetReducerContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ReducerContext(identity, connectionId, random, time)); SpacetimeDB.Internal.Module.SetViewContextConstructor(identity => new SpacetimeDB.ViewContext(identity, new SpacetimeDB.Internal.LocalReadOnly())); @@ -2968,74 +3204,72 @@ public static void Main() { #endif #if NET10_0_OR_GREATER - global::{{extensionNamespaceName}}.AssemblyDescriptor.Register( - global::SpacetimeDB.Internal.Module.RootBuilder); - {{string.Join("\n", - assemblies.Array.Select(a => - $"{a.DescriptorTypeName}.Register(global::SpacetimeDB.Internal.Module.RootBuilder);") - )}} + {{IndentGeneratedCode(string.Join("\n", compositionRegistration), 8)}} #else Register(global::SpacetimeDB.Internal.Module.RootBuilder); #endif } internal static void Register( - global::SpacetimeDB.Internal.ModuleBuilder builder) + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null) { - {{preRegistrations}} + // HTTP routes retain the root routing API even for mounted modules. + httpBuilder ??= builder; + {{IndentGeneratedCode(preRegistrations, 8)}} var __memoryStream = new MemoryStream(); var __writer = new BinaryWriter(__memoryStream); - {{string.Join( + {{IndentGeneratedCode(string.Join( "\n", addReducers.Select(r => $"builder.RegisterReducer<{EscapeIdentifier(r.Name)}>();" ) - )}} - {{string.Join( + ), 8)}} + {{IndentGeneratedCode(string.Join( "\n", addProcedures.Select(r => $"builder.RegisterProcedure<{EscapeIdentifier(r.Name)}>();" ) - )}} - {{string.Join( + ), 8)}} + {{IndentGeneratedCode(string.Join( "\n", addHttpHandlers.Select(r => - $"builder.RegisterHttpHandler<{EscapeIdentifier(r.Name)}>();" + $"httpBuilder.RegisterHttpHandler<{EscapeIdentifier(r.Name)}>();" ) - )}} + ), 8)}} // IMPORTANT: The order in which we register views matters. // It must correspond to the order in which we call `GenerateDispatcherClass`. // See the comment on `GenerateDispatcherClass` for more explanation. - {{string.Join("\n", + {{IndentGeneratedCode(string.Join("\n", views.Array.Where(v => !v.IsAnonymous) .Select(v => $"builder.RegisterView<{v.Name}ViewDispatcher>();") .Concat( views.Array.Where(v => v.IsAnonymous) .Select(v => $"builder.RegisterAnonymousView<{v.Name}ViewDispatcher>();") ) - )}} + ), 8)}} - {{string.Join("\n", + {{IndentGeneratedCode(string.Join("\n", views.Array.Select(v => v.GenerateViewPrimaryKeyRegistration()) .OfType() - )}} + ), 8)}} - {{string.Join( + {{IndentGeneratedCode(string.Join( "\n", - tableAccessors.Select(t => $"builder.RegisterTable<{t.TableName}, SpacetimeDB.Internal.TableHandles.{EscapeIdentifier(t.TableAccessorName)}>();") - )}} - {{( + tableAccessors.Select(t => $"builder.RegisterTable<{t.TableName}, global::{handlesNamespace}.TableHandles.{EscapeIdentifier(t.TableAccessorName)}>();") + ), 8)}} + {{IndentGeneratedCode(( httpRouters.Array.FirstOrDefault(r => r.IsValid) is { } router - ? $"builder.RegisterHttpRouter({router.FullName}());" + ? $"httpBuilder.RegisterHttpRouter({router.FullName}());" : string.Empty - )}} - {{string.Join( + ), 8)}} + {{IndentGeneratedCode(string.Join( "\n", rlsFilters.Select(f => $"builder.RegisterClientVisibilityFilter({f.GlobalName});") - )}} - {{string.Join( + ), 8)}} + {{IndentGeneratedCode(string.Join( "\n", columnDefaultValues.Select(d => "{\n" @@ -3046,7 +3280,7 @@ internal static void Register( + "var array = __memoryStream.ToArray();\n" + $"builder.RegisterTableDefaultValue(\"{d.TableName}\", {d.ColumnId}, array);" + "\n}\n") - )}} + ), 8)}} } // Export entrypoints live in generated module code so all build modes can @@ -3056,7 +3290,7 @@ internal static void Register( #endif public static void __describe_module__(SpacetimeDB.Internal.BytesSink d) => SpacetimeDB.Internal.Module.__describe_module__(d); - {{string.Join( + {{IndentGeneratedCode(string.Join( "\n\n", addReducers.Select((r, i) => $$""" @@ -3084,9 +3318,9 @@ SpacetimeDB.Internal.BytesSink error } """ ) - )}} + ), 4)}} - {{string.Join( + {{IndentGeneratedCode(string.Join( "\n\n", addProcedures.Select((p, i) => $$""" @@ -3116,9 +3350,9 @@ SpacetimeDB.Internal.BytesSink result_sink } """ ) - )}} + ), 4)}} - {{string.Join( + {{IndentGeneratedCode(string.Join( "\n\n", addHttpHandlers.Select((h, i) => $$""" @@ -3144,9 +3378,9 @@ SpacetimeDB.Internal.BytesSink response_body_sink } """ ) - )}} + ), 4)}} - {{string.Join( + {{IndentGeneratedCode(string.Join( "\n\n", views.Array.Where(v => !v.IsAnonymous).Select((v, i) => $$""" @@ -3172,9 +3406,9 @@ SpacetimeDB.Internal.BytesSink sink } """ ) - )}} + ), 4)}} - {{string.Join( + {{IndentGeneratedCode(string.Join( "\n\n", views.Array.Where(v => v.IsAnonymous).Select((v, i) => $$""" @@ -3196,7 +3430,7 @@ SpacetimeDB.Internal.BytesSink sink } """ ) - )}} + ), 4)}} #if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER [UnmanagedCallersOnly(EntryPoint = "__call_reducer__")] @@ -3212,13 +3446,32 @@ public static SpacetimeDB.Internal.Errno __call_reducer__( SpacetimeDB.Timestamp timestamp, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink error + ) { + #if NET10_0_OR_GREATER + {{IndentGeneratedCode(GenerateDispatchRouting("Reducer", "sender_0, sender_1, sender_2, sender_3, conn_id_0, conn_id_1, timestamp, args, error", "return SpacetimeDB.Internal.Module.WriteReducerError(error, new System.ArgumentOutOfRangeException(nameof(id), id, \"Unknown reducer id\"));"), 8)}} + #else + return CallLocalReducer(id, sender_0, sender_1, sender_2, sender_3, conn_id_0, conn_id_1, timestamp, args, error); + #endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error ) => id switch { - {{string.Join( + {{IndentGeneratedCode(string.Join( "\n", addReducers.Select((r, i) => $"{i} => __call_reducer_{i}(sender_0, sender_1, sender_2, sender_3, conn_id_0, conn_id_1, timestamp, args, error)," ) - )}} + ), 8)}} _ => SpacetimeDB.Internal.Module.WriteReducerError(error, new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id")) }; @@ -3236,13 +3489,32 @@ public static SpacetimeDB.Internal.Errno __call_procedure__( SpacetimeDB.Timestamp timestamp, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink result_sink + ) { + #if NET10_0_OR_GREATER + {{IndentGeneratedCode(GenerateDispatchRouting("Procedure", "sender_0, sender_1, sender_2, sender_3, conn_id_0, conn_id_1, timestamp, args, result_sink", "throw new System.ArgumentOutOfRangeException(nameof(id), id, \"Unknown procedure id\");"), 8)}} + #else + return CallLocalProcedure(id, sender_0, sender_1, sender_2, sender_3, conn_id_0, conn_id_1, timestamp, args, result_sink); + #endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink result_sink ) => id switch { - {{string.Join( + {{IndentGeneratedCode(string.Join( "\n", addProcedures.Select((p, i) => $"{i} => __call_procedure_{i}(sender_0, sender_1, sender_2, sender_3, conn_id_0, conn_id_1, timestamp, args, result_sink)," ) - )}} + ), 8)}} _ => throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id") }; @@ -3256,13 +3528,28 @@ public static SpacetimeDB.Internal.Errno __call_http_handler__( SpacetimeDB.Internal.BytesSource request_body, SpacetimeDB.Internal.BytesSink response_sink, SpacetimeDB.Internal.BytesSink response_body_sink + ) { + #if NET10_0_OR_GREATER + {{IndentGeneratedCode(GenerateDispatchRouting("HttpHandler", "timestamp, request, request_body, response_sink, response_body_sink", "throw new System.ArgumentOutOfRangeException(nameof(id), id, \"Unknown HTTP handler id\");"), 8)}} + #else + return CallLocalHttpHandler(id, timestamp, request, request_body, response_sink, response_body_sink); + #endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource request, + SpacetimeDB.Internal.BytesSource request_body, + SpacetimeDB.Internal.BytesSink response_sink, + SpacetimeDB.Internal.BytesSink response_body_sink ) => id switch { - {{string.Join( + {{IndentGeneratedCode(string.Join( "\n", addHttpHandlers.Select((h, i) => $"{i} => __call_http_handler_{i}(timestamp, request, request_body, response_sink, response_body_sink)," ) - )}} + ), 8)}} _ => throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id") }; @@ -3277,13 +3564,29 @@ public static SpacetimeDB.Internal.Errno __call_view__( ulong sender_3, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink sink + ) { + #if NET10_0_OR_GREATER + {{IndentGeneratedCode(GenerateDispatchRouting("View", "sender_0, sender_1, sender_2, sender_3, args, sink", "return UnknownViewId(id);"), 8)}} + #else + return CallLocalView(id, sender_0, sender_1, sender_2, sender_3, args, sink); + #endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink ) => id switch { - {{string.Join("\n", + {{IndentGeneratedCode(string.Join("\n", views.Array.Where(v => !v.IsAnonymous) .Select((v, i) => $"{i} => __call_view_{i}(sender_0, sender_1, sender_2, sender_3, args, sink)," ) - )}} + ), 8)}} _ => UnknownViewId(id) }; @@ -3294,13 +3597,25 @@ public static SpacetimeDB.Internal.Errno __call_view_anon__( int id, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink sink + ) { + #if NET10_0_OR_GREATER + {{IndentGeneratedCode(GenerateDispatchRouting("AnonymousView", "args, sink", "return UnknownAnonymousViewId(id);"), 8)}} + #else + return CallLocalAnonymousView(id, args, sink); + #endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink ) => id switch { - {{string.Join("\n", + {{IndentGeneratedCode(string.Join("\n", views.Array.Where(v => v.IsAnonymous) .Select((v, i) => $"{i} => __call_view_anon_{i}(args, sink)," ) - )}} + ), 8)}} _ => UnknownAnonymousViewId(id) }; diff --git a/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs b/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs new file mode 100644 index 00000000000..dcf1e26d419 --- /dev/null +++ b/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs @@ -0,0 +1,147 @@ +namespace SpacetimeDB.Codegen; + +using System.Collections.Immutable; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using static Utils; + +record NamespaceDeclaration(string AssemblyIdentity, string Accessor, string Name) +{ + public string AccessorIdentifier => EscapeIdentifier(Accessor); + + public static EquatableArray Parse( + Compilation compilation, + EquatableArray assemblies, + IEnumerable tableAccessors, + DiagReporter diag, + CancellationToken cancellationToken + ) + { + var attributeType = compilation.GetTypeByMetadataName("SpacetimeDB.NamespaceAttribute"); + var result = ImmutableArray.CreateBuilder(); + if (attributeType is null) + return new(result.ToImmutable()); + var identities = new Dictionary(StringComparer.Ordinal); + var names = new Dictionary(StringComparer.OrdinalIgnoreCase); + var accessors = new Dictionary(StringComparer.Ordinal); + var tables = new HashSet(tableAccessors, StringComparer.Ordinal); + var supported = compilation.SyntaxTrees.Any(tree => + tree.Options is CSharpParseOptions options + && options.PreprocessorSymbolNames.Contains("NET10_0_OR_GREATER") + // Use the numeric value to keep the analyzer compatible with Roslyn 4.3. + && (int)options.LanguageVersion >= 1400 + ); + + foreach (var attribute in compilation.Assembly.GetAttributes()) + { + cancellationToken.ThrowIfCancellationRequested(); + if (!SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, attributeType)) + continue; + + var valid = true; + void Error(string message) + { + valid = false; + diag.Report(ErrorDescriptor.InvalidNamespace, (attribute, message)); + } + + if (!supported) + Error("Namespace mounts require .NET 10 and C# 14."); + + if ( + attribute.ConstructorArguments.Length != 1 + || attribute.ConstructorArguments[0].Value is not INamedTypeSymbol marker + ) + { + Error("A namespace mount requires a marker type declared in a module assembly."); + continue; + } + + var identity = marker.ContainingAssembly.Identity.ToString(); + if ( + SymbolEqualityComparer.Default.Equals( + marker.ContainingAssembly, + compilation.Assembly + ) + ) + Error("The root assembly cannot mount itself."); + else if (supported && !assemblies.Any(a => a.Identity == identity)) + Error($"Assembly '{identity}' has no discovered module descriptor."); + + var accessor = + attribute.NamedArguments.FirstOrDefault(a => a.Key == "Accessor").Value.Value + as string + ?? ""; + var name = + attribute.NamedArguments.FirstOrDefault(a => a.Key == "Name").Value.Value as string + ?? ""; + // Keywords are stored unescaped and escaped only when rendering C#. + if ( + accessor.Length == 0 + || accessor[0] == '@' + || !( + SyntaxFacts.IsValidIdentifier(accessor) + || SyntaxFacts.GetKeywordKind(accessor) != SyntaxKind.None + ) + || SyntaxFactory.ParseToken(EscapeIdentifier(accessor)).ValueText != accessor + ) + Error("Accessor must be a nonempty C# identifier (use keyword names without '@')."); + + // Keep database names separate from C# identifier/keyword rules. + // The host remains authoritative for full Unicode identifier validation. + if ( + name.Length == 0 + || !(char.IsLetter(name[0]) || name[0] == '_') + || name.Any(c => !(char.IsLetterOrDigit(c) || c == '_')) + || !name.IsNormalized(NormalizationForm.FormC) + ) + Error( + "Name must be a nonempty database identifier: letters, digits or underscores, starting with a letter or underscore." + ); + if (Encoding.UTF8.GetByteCount(name) > 63) + Error("Namespace names cannot exceed 63 UTF-8 bytes (the current host limit)."); + if ( + name.Equals("st", StringComparison.OrdinalIgnoreCase) + || name.Equals("spacetimedb", StringComparison.OrdinalIgnoreCase) + || name.StartsWith("pg_", StringComparison.OrdinalIgnoreCase) + ) + Error($"Namespace '{name}' is reserved."); + + void CheckDuplicate(Dictionary seen, string key, string message) + { + if (seen.TryGetValue(key, out var previous)) + { + Error(message); + diag.Report(ErrorDescriptor.InvalidNamespace, (previous, message)); + } + else + seen.Add(key, attribute); + } + + CheckDuplicate( + identities, + identity, + $"Assembly '{identity}' may only be mounted once." + ); + if (name.Length > 0) + CheckDuplicate( + names, + name, + $"Namespace '{name}' is declared more than once (case-insensitive)." + ); + if (accessor.Length > 0) + CheckDuplicate( + accessors, + accessor, + $"Namespace accessor '{accessor}' is declared more than once." + ); + if (tables.Contains(accessor)) + Error($"Namespace accessor '{accessor}' conflicts with a root table accessor."); + + if (valid) + result.Add(new(identity, accessor, name)); + } + return new(result.ToImmutable()); + } +} diff --git a/crates/bindings-csharp/Runtime/Attrs.cs b/crates/bindings-csharp/Runtime/Attrs.cs index d80caa3d7be..121b8be9391 100644 --- a/crates/bindings-csharp/Runtime/Attrs.cs +++ b/crates/bindings-csharp/Runtime/Attrs.cs @@ -1,5 +1,24 @@ namespace SpacetimeDB { +#if NET10_0_OR_GREATER + /// + /// Places the module contributions of the marker type's assembly in a namespace. + /// The consuming module chooses the placement; the marker may be any accessible type. + /// Requires .NET 10 and C# 14. + /// + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class NamespaceAttribute(System.Type marker) : Attribute + { + public System.Type Marker { get; } = marker; + + /// The C# member name used to access the mounted module. + public string Accessor { get; set; } = ""; + + /// The database namespace, independent of the C# accessor. + public string Name { get; set; } = ""; + } +#endif + /// Declares the complete environment schema for this module. [AttributeUsage(AttributeTargets.Struct)] public sealed class EnvAttribute : Attribute { } diff --git a/crates/bindings-csharp/Runtime/Internal/ITable.cs b/crates/bindings-csharp/Runtime/Internal/ITable.cs index 51e6fa0e6ee..4ea680b97f3 100644 --- a/crates/bindings-csharp/Runtime/Internal/ITable.cs +++ b/crates/bindings-csharp/Runtime/Internal/ITable.cs @@ -82,6 +82,8 @@ public interface ITableView static abstract T ReadGenFields(BinaryReader reader, T row); + static virtual string LookupName => tableName; + // These are static helpers that codegen can use. private class RawTableIter(FFI.TableId tableId) : RawTableIterBase @@ -96,7 +98,7 @@ protected override void IterStart(out FFI.RowIter handle) => private static readonly Lazy tableId_ = new(() => { - var name_bytes = System.Text.Encoding.UTF8.GetBytes(tableName); + var name_bytes = System.Text.Encoding.UTF8.GetBytes(View.LookupName); FFI.table_id_from_name(name_bytes, name_bytes.Length, out var out_); return out_; }); diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index 9750c414d69..6a5679f86a7 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -44,6 +44,19 @@ private static void EnsureNativeAotTypeRoots() private static readonly ModuleBuilder moduleDef = new(); public static ModuleBuilder RootBuilder => moduleDef; + private static NamespaceRegistry? namespaces; + + public static void InstallNamespaces(NamespaceRegistry registry) + { + if (namespaces is not null) + throw new InvalidOperationException("Module namespaces have already been installed."); + namespaces = registry; + } + + public static string ResolveName(string assemblyIdentity, string localName) => + (namespaces ?? throw new InvalidOperationException("Module namespaces have not been installed.")) + .Resolve(assemblyIdentity, localName); + private static Func< Identity, ConnectionId?, diff --git a/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs b/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs index 2f0cc831bbd..cf172d9dedf 100644 --- a/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs +++ b/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs @@ -73,6 +73,9 @@ private static RawScopedTypeNameV10 MakeScopedTypeName(Type type) => internal void RegisterSubmodule(RawSubmoduleV10 submodule) => submoduleDefs.Add(submodule); + public void RegisterSubmodule(string name, ModuleBuilder child) => + RegisterSubmodule(new RawSubmoduleV10(name, child.BuildModuleDefinition())); + // Receives types to store the reference in the dictionary so that we can resolve it later and to avoid infinite recursion inside `makeType`. internal AlgebraicType.Ref RegisterType( Dictionary types, @@ -189,7 +192,13 @@ public void RegisterAnonymousView() RegisterView(def); } - internal void RegisterView(RawViewDefV10 view) => viewDefs.Add(view); + internal void RegisterView(RawViewDefV10 view) + { + // Several descriptors may share this builder. IDs are local to the composed + // definition, with independent sequences for anonymous and sender views. + view.Index = (uint)viewDefs.Count(previous => previous.IsAnonymous == view.IsAnonymous); + viewDefs.Add(view); + } internal void RegisterEnvironment(EnvironmentDeclaration declaration) => environment.Add(declaration); diff --git a/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs b/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs new file mode 100644 index 00000000000..510ec259168 --- /dev/null +++ b/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs @@ -0,0 +1,27 @@ +namespace SpacetimeDB.Internal; + +/// Immutable assembly placement installed before module registration. +public sealed class NamespaceRegistry +{ + private readonly Dictionary mounts = new(StringComparer.Ordinal); + + public NamespaceRegistry(string rootIdentity, IEnumerable> mounts) + { + foreach (var mount in mounts) + { + if (mount.Key == rootIdentity) + throw new ArgumentException("The root assembly cannot be mounted.", nameof(mounts)); + if (!this.mounts.TryAdd(mount.Key, mount.Value)) + throw new ArgumentException( + $"Assembly '{mount.Key}' is mounted more than once.", + nameof(mounts) + ); + } + } + + public string Resolve(string assemblyIdentity, string localName) => + mounts.TryGetValue(assemblyIdentity, out var name) + && !name.Equals("public", StringComparison.OrdinalIgnoreCase) + ? name + "." + localName + : localName; +} diff --git a/crates/testing/tests/standalone_integration_test.rs b/crates/testing/tests/standalone_integration_test.rs index 139da0575b4..c5dd49954d1 100644 --- a/crates/testing/tests/standalone_integration_test.rs +++ b/crates/testing/tests/standalone_integration_test.rs @@ -121,6 +121,79 @@ fn namespace_csharp_root_selected_at_publish() { |module| async move { module.call_reducer_binary("consumer_entry", &product![]).await.unwrap(); assert!(module.read_log(None).await.contains("consumer published as root")); + module + .call_reducer_binary("dependency_entry", &product![]) + .await + .unwrap(); + assert!(module.read_log(None).await.contains("dependency published as root")); + }, + ); +} + +#[test] +#[serial] +fn namespace_csharp_mounted_dependencies() { + init(); + CompiledModule::compile("namespace-test-cs", CompilationMode::Debug).with_module_async( + DEFAULT_CONFIG, + |mut module| async move { + // Extra is discovered without any application reference to its helpers. + module.call_reducer_binary("extra", &product![]).await.unwrap(); + module.call_reducer_binary("exercise", &product![]).await.unwrap(); + assert!(module.read_log(None).await.contains("namespace composition works")); + module + .call_reducer_binary("auth_data.add", &product![10u32]) + .await + .unwrap(); + module + .call_reducer_binary("audit_data.add", &product![11u32]) + .await + .unwrap(); + assert_eq!( + module.call_procedure_with_args("count_users", "[]").await.unwrap(), + AlgebraicValue::U64(5) + ); + for name in ["auth_data.count_users", "audit_data.count_users"] { + assert_eq!( + module.call_procedure_with_args(name, "[]").await.unwrap(), + AlgebraicValue::U64(2) + ); + } + assert_eq!(module.call_http_route_get("/auth-count").await.unwrap().as_ref(), b"2"); + + module + .client + .subscribe( + spacetimedb_client_api_messages::websocket::v1::Subscribe { + query_strings: [ + "SELECT * FROM users", + "SELECT * FROM auth_users", + "SELECT * FROM extra_rows", + "SELECT * FROM auth_data.users", + "SELECT * FROM auth_data.anonymous_users", + ] + .map(Box::::from) + .into(), + request_id: 99, + }, + Instant::now(), + ) + .await + .unwrap(); + tokio::time::timeout(Duration::from_secs(10), async { + while let Some(message) = module.recv_message().await { + if let spacetimedb::client::OutboundMessage::V1( + message @ spacetimedb::client::messages::SerializableMessage::Subscribe(_), + ) = message + { + assert_eq!(message.num_rows(), Some(5)); + return; + } + } + panic!("connection closed before the view subscription response"); + }) + .await + .unwrap(); }, ); } diff --git a/modules/namespace-test-cs/Lib.cs b/modules/namespace-test-cs/Lib.cs new file mode 100644 index 00000000000..cdde9db4383 --- /dev/null +++ b/modules/namespace-test-cs/Lib.cs @@ -0,0 +1,60 @@ +using SpacetimeDB; + +[assembly: Namespace(typeof(AuthLib.Marker), Accessor = "MyAuth", Name = "auth_data")] +[assembly: Namespace(typeof(AuditLib.Marker), Accessor = "class", Name = "audit_data")] + +namespace NamespaceRoot; + +[Table(Accessor = "User", Public = true)] +public partial struct User +{ + [PrimaryKey] + public uint Id; +} + +[SpacetimeDB.Type] +public partial struct AuthSummary +{ + public uint Score; +} + +public static partial class Functions +{ + [Reducer] + public static void Exercise(ReducerContext ctx) + { + ctx.Db.User.Insert(new User { Id = 1 }); + AuthLib.Functions.Insert(ctx, 2); + ctx.Db.MyAuth.User.Insert(new AuthLib.User { Id = 3, Score = 43 }); + ctx.Db.@class.User.Insert(new AuditLib.User { Id = 4, Message = "consumer" }); + if ( + ctx.Db.User.Count != 1 + || AuthLib.Functions.Count(ctx) != 2 + || ctx.Db.@class.User.Count != 1 + || ctx.Db.ExtraRow.Count != 1 + ) + throw new Exception("Namespace counts are not isolated."); + var row = ctx.Db.MyAuth.User.Id.Find(2)!.Value; + row.Score = 99; + ctx.Db.MyAuth.User.Id.Update(row); + if (ctx.Db.MyAuth.User.ByScore.Filter(99u).Single().Id != 2) + throw new Exception("Mounted index lookup failed."); + if (!ctx.Db.MyAuth.User.Id.Delete(3) || ctx.Db.MyAuth.User.Count != 1) + throw new Exception("Mounted unique deletion failed."); + Log.Info("namespace composition works"); + } + + [Procedure] + public static ulong CountUsers(ProcedureContext ctx) => + ctx.WithTx(tx => tx.Db.User.Count + tx.Db.MyAuth.User.Count + tx.Db.@class.User.Count); + + [View(Accessor = "Users", Public = true)] + public static User? Users(ViewContext ctx) => ctx.Db.User.Id.Find(1); + + [View(Accessor = "AuthUsers", Public = true)] + public static List AuthUsers(ViewContext ctx) => + ctx + .Db.MyAuth.User.ByScore.Filter(99u) + .Select(row => new AuthSummary { Score = row.Score }) + .ToList(); +} diff --git a/modules/namespace-test-cs/libraries/AuditLib/AuditLib.csproj b/modules/namespace-test-cs/libraries/AuditLib/AuditLib.csproj new file mode 100644 index 00000000000..1de85406f46 --- /dev/null +++ b/modules/namespace-test-cs/libraries/AuditLib/AuditLib.csproj @@ -0,0 +1,11 @@ + + + net10.0 + NamespaceAuditLib + $(AssemblyName) + + + + + + diff --git a/modules/namespace-test-cs/libraries/AuditLib/Lib.cs b/modules/namespace-test-cs/libraries/AuditLib/Lib.cs new file mode 100644 index 00000000000..ccab3d00dd6 --- /dev/null +++ b/modules/namespace-test-cs/libraries/AuditLib/Lib.cs @@ -0,0 +1,23 @@ +using SpacetimeDB; + +namespace AuditLib; + +public class Marker { } + +[Table(Accessor = "User", Public = true)] +public partial struct User +{ + [PrimaryKey] + public uint Id; + public string Message; +} + +public static partial class Functions +{ + [Reducer] + public static void Add(ReducerContext ctx, uint id) => + ctx.Db.User.Insert(new User { Id = id, Message = "audit" }); + + [Procedure] + public static ulong CountUsers(ProcedureContext ctx) => ctx.WithTx(tx => tx.Db.User.Count); +} diff --git a/modules/namespace-test-cs/libraries/AuthLib/AuthLib.csproj b/modules/namespace-test-cs/libraries/AuthLib/AuthLib.csproj new file mode 100644 index 00000000000..1e9afde0747 --- /dev/null +++ b/modules/namespace-test-cs/libraries/AuthLib/AuthLib.csproj @@ -0,0 +1,11 @@ + + + net10.0 + NamespaceAuthLib + $(AssemblyName) + + + + + + diff --git a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs new file mode 100644 index 00000000000..5c4db70015e --- /dev/null +++ b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs @@ -0,0 +1,49 @@ +using SpacetimeDB; + +#pragma warning disable STDB_UNSTABLE + +namespace AuthLib; + +public class Marker { } + +[Table(Accessor = "User", Name = "auth_users", Public = true)] +[SpacetimeDB.Index.BTree(Accessor = "ByScore", Columns = [nameof(Score)])] +public partial struct User +{ + [PrimaryKey] + public uint Id; + public uint Score; +} + +public static partial class Functions +{ + public static void Insert(ReducerContext ctx, uint id) => + ctx.Db.User.Insert(new User { Id = id, Score = 42 }); + + public static ulong Count(ReducerContext ctx) => ctx.Db.User.Count; + + [Reducer] + public static void Add(ReducerContext ctx, uint id) => Insert(ctx, id); + + [Procedure] + public static ulong CountUsers(ProcedureContext ctx) => ctx.WithTx(tx => tx.Db.User.Count); + + [View(Accessor = "Users", Public = true)] + public static User? Users(ViewContext ctx) => ctx.Db.User.Id.Find(2); + + [View(Accessor = "AnonymousUsers", Public = true)] + public static User? AnonymousUsers(AnonymousViewContext ctx) => ctx.Db.User.Id.Find(2); + + [HttpHandler] + public static HttpResponse AuthCount(HandlerContext ctx, HttpRequest request) => + new( + 200, + HttpVersion.Http11, + [], + HttpBody.FromString(ctx.WithTx(tx => tx.Db.User.Count).ToString()) + ); + + [HttpRouter] + public static Router Routes() => + Router.New().Get("/auth-count", new Handler(nameof(AuthCount))); +} diff --git a/modules/namespace-test-cs/libraries/ExtraLib/ExtraLib.csproj b/modules/namespace-test-cs/libraries/ExtraLib/ExtraLib.csproj new file mode 100644 index 00000000000..5005d086a77 --- /dev/null +++ b/modules/namespace-test-cs/libraries/ExtraLib/ExtraLib.csproj @@ -0,0 +1,11 @@ + + + net10.0 + NamespaceExtraLib + $(AssemblyName) + + + + + + diff --git a/modules/namespace-test-cs/libraries/ExtraLib/Lib.cs b/modules/namespace-test-cs/libraries/ExtraLib/Lib.cs new file mode 100644 index 00000000000..d3688e339fe --- /dev/null +++ b/modules/namespace-test-cs/libraries/ExtraLib/Lib.cs @@ -0,0 +1,19 @@ +using SpacetimeDB; + +namespace ExtraLib; + +[Table(Public = true)] +public partial struct ExtraRow +{ + [PrimaryKey] + public uint Id; +} + +public static partial class Functions +{ + [Reducer] + public static void Extra(ReducerContext ctx) => ctx.Db.ExtraRow.Insert(new ExtraRow { Id = 7 }); + + [View(Accessor = "ExtraRows", Public = true)] + public static ExtraRow? Rows(ViewContext ctx) => ctx.Db.ExtraRow.Id.Find(7); +} diff --git a/modules/namespace-test-cs/namespace-test-cs.csproj b/modules/namespace-test-cs/namespace-test-cs.csproj new file mode 100644 index 00000000000..c662db79336 --- /dev/null +++ b/modules/namespace-test-cs/namespace-test-cs.csproj @@ -0,0 +1,13 @@ + + + net10.0 + + + + + + + + + + From c6e27a0a55f1ca29747f3e6ad5e4062426bdce84 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Wed, 16 Sep 2026 14:43:44 -0500 Subject: [PATCH 08/49] Module-side ctx.Db and ctx.From now work --- .../BSATN.Runtime/QueryBuilder.cs | 61 +++++++++++-- crates/bindings-csharp/Codegen.Tests/Tests.cs | 14 +++ crates/bindings-csharp/Codegen/Module.cs | 85 +++++++++++++++---- .../Runtime/Internal/Module.cs | 4 + .../Runtime/Internal/NamespaceRegistry.cs | 14 ++- .../tests/standalone_integration_test.rs | 6 +- modules/namespace-test-cs/Lib.cs | 16 +++- .../libraries/AuthLib/Lib.cs | 6 ++ sdks/csharp/tests~/QueryBuilderTests.cs | 39 +++++++++ 9 files changed, 215 insertions(+), 30 deletions(-) diff --git a/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs b/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs index e8d52a084e6..0c9c561ffae 100644 --- a/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs +++ b/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs @@ -1,8 +1,46 @@ namespace SpacetimeDB; using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Globalization; +/// A table identifier with separately quoted namespace segments and local name. +public readonly struct SqlTableName +{ + private readonly ReadOnlyCollection? namespaceSegments; + public IReadOnlyList NamespaceSegments => + namespaceSegments ?? (IReadOnlyList)[]; + public string LocalName { get; } + + public SqlTableName(string localName) + { + LocalName = localName; + namespaceSegments = null; + } + + public SqlTableName(string[] namespaceSegments, string localName) + { +#if NET8_OR_GREATER + ArgumentNullException.ThrowIfNull(namespaceSegments); +#else + if (namespaceSegments is null) + throw new ArgumentNullException(nameof(namespaceSegments)); +#endif + this.namespaceSegments = Array.AsReadOnly((string[])namespaceSegments.Clone()); + LocalName = localName; + } + + public override string ToString() + { + var sql = ""; + if (namespaceSegments is not null) + foreach (var segment in namespaceSegments) + sql += SqlFormat.QuoteIdent(segment) + "."; + return sql + SqlFormat.QuoteIdent(LocalName); + } +} + public readonly struct SqlLiteral { internal string Sql { get; } @@ -113,11 +151,14 @@ internal IxJoinEq(string leftRefSql, string rightRefSql) } } -public readonly struct Col(string tableName, string columnName) +public readonly struct Col(SqlTableName tableName, string columnName) where TValue : notnull { + public Col(string tableName, string columnName) + : this(new SqlTableName(tableName), columnName) { } + internal string RefSql => - $"{SqlFormat.QuoteIdent(tableName)}.{SqlFormat.QuoteIdent(columnName)}"; + $"{tableName}.{SqlFormat.QuoteIdent(columnName)}"; public BoolExpr Eq(SqlLiteral value) => new($"({RefSql} = {value.Sql})"); @@ -146,11 +187,14 @@ public readonly struct Col(string tableName, string columnName) public override string ToString() => RefSql; } -public readonly struct IxCol(string tableName, string columnName) +public readonly struct IxCol(SqlTableName tableName, string columnName) where TValue : notnull { + public IxCol(string tableName, string columnName) + : this(new SqlTableName(tableName), columnName) { } + internal string RefSql => - $"{SqlFormat.QuoteIdent(tableName)}.{SqlFormat.QuoteIdent(columnName)}"; + $"{tableName}.{SqlFormat.QuoteIdent(columnName)}"; public BoolExpr Eq(SqlLiteral value) => new($"({RefSql} = {value.Sql})"); @@ -162,16 +206,19 @@ public IxJoinEq Eq(IxCol other) = public override string ToString() => RefSql; } -public sealed class Table(string tableName, TCols cols, TIxCols ixCols) +public sealed class Table(SqlTableName tableName, TCols cols, TIxCols ixCols) : IQuery { - internal string TableRefSql => SqlFormat.QuoteIdent(tableName); + public Table(string tableName, TCols cols, TIxCols ixCols) + : this(new SqlTableName(tableName), cols, ixCols) { } + + internal string TableRefSql => tableName.ToString(); internal TCols Cols => cols; internal TIxCols IxCols => ixCols; - public string ToSql() => $"SELECT * FROM {SqlFormat.QuoteIdent(tableName)}"; + public string ToSql() => $"SELECT * FROM {TableRefSql}"; public FromWhere Where(Func predicate) => new(this, QueryPredicate.ToBoolExpr(predicate(cols)!)); diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 2cfb1eb1bb6..aa36c8fffc8 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -482,6 +482,9 @@ namespace {{name}} { public class Sentinel { } [SpacetimeDB.Table] public partial struct {{name}}Row { public uint Id; } + public static class QueryHelpers { + public static SpacetimeDB.IQuery<{{name}}Row> Query(SpacetimeDB.AnonymousViewContext ctx) => ctx.From.{{name}}Row().Where(c => c.Id.Eq(SpacetimeDB.SqlLit.Int(1u))); + } } """; string Descriptor(CSharpCompilation compilation) => Assert.Single( @@ -511,6 +514,13 @@ MethodDeclarationSyntax Method(CSharpCompilation compilation, string name) => As + "[assembly: SpacetimeDB.Namespace(typeof(Beta.Sentinel), Accessor = \"class\", Name = \"audit_data\")]\n" + rootSource + "public static class Helpers { public static ulong Count(SpacetimeDB.ReducerContext ctx) => ctx.Db.Auth.AlphaRow.Count + ctx.Db.@class.BetaRow.Count + ctx.Db.SharedRow.Count; }"; + rootSource += $$""" + public static class RootQueries { + public static SpacetimeDB.IQuery Alpha(SpacetimeDB.ViewContext ctx) => ctx.From.{{(mounted ? "Auth." : "")}}AlphaRow(); + public static SpacetimeDB.IQuery Beta(SpacetimeDB.AnonymousViewContext ctx) => ctx.From.{{(mounted ? "@class." : "")}}BetaRow(); + public static SpacetimeDB.IQuery Shared(SpacetimeDB.ViewContext ctx) => ctx.From.SharedRow(); + } + """; var root = Generate(Create("Root", rootSource, beta, utility, shared, alpha)); var reordered = Generate(Create("Root", rootSource, alpha, shared, utility, beta)); Emit(root); @@ -738,6 +748,10 @@ public static bool CheckNamespaces() catch (System.InvalidOperationException) { } SpacetimeDB.Internal.Module.InstallNamespaces(registry); if (SpacetimeDB.Internal.Module.ResolveName(first, "User") != "auth_data.User") return false; + if (SpacetimeDB.Internal.Module.ResolveSqlName(first, "User").ToString() != "\"auth_data\".\"User\"") return false; + if (registry.ResolveSqlName("unmounted", "User").ToString() != "\"User\"") return false; + if (registry.ResolveSqlName("merged", "User").ToString() != "\"User\"") return false; + if (registry.ResolveSqlName("root", "User.With.Dot").ToString() != "\"User.With.Dot\"") return false; try { SpacetimeDB.Internal.Module.InstallNamespaces(registry); return false; } catch (System.InvalidOperationException) { } try { new NamespaceRegistry(first, placements); return false; } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 5d059815e4e..618529c01e0 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -1007,13 +1007,44 @@ string IxColInit(ColumnDeclaration col) var ixColsDecls = string.Join("\n ", ixMembers.Select(IxColDecl)); var ixColsInits = string.Join("\n ", ixMembers.Select(IxColInit)); + var nameType = useExtensions ? "global::SpacetimeDB.SqlTableName" : "string"; + var queryType = $"global::SpacetimeDB.Table<{globalRowName}, {colsTypeName}, {ixColsTypeName}>"; + var queryMember = useExtensions + ? $$""" + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + {{vis}} {{queryType}} {{accessorIdentifier}}() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName({{SymbolDisplay.FormatLiteral(assemblyIdentity, true)}}, {{SymbolDisplay.FormatLiteral(tableName, true)}}); + return new(tableName, new {{colsTypeName}}(tableName), new {{ixColsTypeName}}(tableName)); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + {{vis}} {{queryType}} {{accessorIdentifier}}() => new AssemblyDescriptor.Queries().{{accessorIdentifier}}(); + } + } + """ + : $$""" + public readonly partial struct QueryBuilder + { + {{vis}} {{queryType}} {{accessorIdentifier}}() => + new("{{tableName}}", new {{colsTypeName}}("{{tableName}}"), new {{ixColsTypeName}}("{{tableName}}")); + } + """; yield return $$""" {{vis}} readonly struct {{colsTypeName}} { {{colsDecls}} - internal {{colsTypeName}}(string tableName) + internal {{colsTypeName}}({{nameType}} tableName) { {{colsInits}} } @@ -1023,17 +1054,13 @@ string IxColInit(ColumnDeclaration col) { {{ixColsDecls}} - internal {{ixColsTypeName}}(string tableName) + internal {{ixColsTypeName}}({{nameType}} tableName) { {{ixColsInits}} } } - {{(useExtensions ? "public static partial class QueryTableExtensions" : "public readonly partial struct QueryBuilder")}} - { - {{(useExtensions ? " extension(global::SpacetimeDB.QueryBuilder from) {\n " : " ")}}{{vis}} global::SpacetimeDB.Table<{{globalRowName}}, {{colsTypeName}}, {{ixColsTypeName}}> {{accessorIdentifier}}() => - {{(useExtensions ? " " : " ")}}new("{{tableName}}", new {{colsTypeName}}("{{tableName}}"), new {{ixColsTypeName}}("{{tableName}}")); - {{(useExtensions ? " }\n" : "")}}} + {{queryMember}} """; } } @@ -2048,7 +2075,8 @@ record AssemblyDeclaration( bool DeclaresMounts, string LifecycleReducers, EquatableArray Tables, - EquatableArray ReadOnlyTables + EquatableArray ReadOnlyTables, + EquatableArray Queries ); [Generator] @@ -2130,7 +2158,16 @@ marker is null descriptor.GetMembers("LifecycleReducers").OfType() .FirstOrDefault()?.ConstantValue as string ?? "", ReadAccessors("Tables"), - ReadAccessors("ReadOnlyTables") + ReadAccessors("ReadOnlyTables"), + new(descriptor.GetTypeMembers("Queries").SelectMany(type => type.GetMembers()) + .OfType() + .Where(method => method.DeclaredAccessibility == Accessibility.Public + && method.MethodKind == MethodKind.Ordinary && method.Parameters.IsEmpty + && !method.IsStatic) + .Select(method => new AssemblyTableAccessor( + method.Name, + method.ReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + )).ToImmutableArray()) ) ); @@ -2617,7 +2654,7 @@ string GenerateDispatchRouting(string category, string arguments, string unknown columnDefaultValues ) = inputs; - string ConsumerAccessors(bool readOnly) + string ConsumerAccessors(string container) { var members = new List(); var used = new Dictionary(StringComparer.Ordinal); @@ -2627,7 +2664,7 @@ void Add(string name, string owner, string declaration) { if (used.TryGetValue(name, out var previous)) { - if (!readOnly) + if (container == "Tables") context.ReportDiagnostic(ErrorDescriptor.NamespaceAccessorCollision.ToDiag( (name, previous, owner))); return; @@ -2639,21 +2676,28 @@ void Add(string name, string owner, string declaration) { if (mountByIdentity.TryGetValue(assembly.Identity, out var mount)) { - var container = readOnly ? "ReadOnlyTables" : "Tables"; Add(mount.Accessor, assembly.Identity, $"public {assembly.DescriptorTypeName}.{container} {mount.AccessorIdentifier} => new();"); } else { - foreach (var table in readOnly ? assembly.ReadOnlyTables : assembly.Tables) + var accessors = container switch + { + "ReadOnlyTables" => assembly.ReadOnlyTables, + "Queries" => assembly.Queries, + _ => assembly.Tables, + }; + var invocation = container == "Queries" ? "()" : ""; + foreach (var table in accessors) Add(table.Name, assembly.Identity, - $"public {table.TypeName} {EscapeIdentifier(table.Name)} => new {assembly.DescriptorTypeName}.{(readOnly ? "ReadOnlyTables" : "Tables")}().{EscapeIdentifier(table.Name)};"); + $"public {table.TypeName} {EscapeIdentifier(table.Name)}{invocation} => new {assembly.DescriptorTypeName}.{container}().{EscapeIdentifier(table.Name)}{invocation};"); } } return string.Join("\n", members); } - var consumerWritableAccessors = ConsumerAccessors(false); - var consumerReadOnlyAccessors = ConsumerAccessors(true); + var consumerWritableAccessors = ConsumerAccessors("Tables"); + var consumerReadOnlyAccessors = ConsumerAccessors("ReadOnlyTables"); + var consumerQueryAccessors = ConsumerAccessors("Queries"); var compositionRegistration = new List { @@ -3039,7 +3083,7 @@ internal AnonymousViewContext(Internal.LocalReadOnly db) #if NET10_0_OR_GREATER namespace {{extensionNamespaceName}} { - public static class AssemblyDescriptor { + public static partial class AssemblyDescriptor { public const string LifecycleReducers = {{SymbolDisplay.FormatLiteral(string.Join(", ", addReducers.Where(r => r.Kind != ReducerKind.UserDefined).Select(r => $"{r.FullName} ({r.Kind})")), true)}}; public const int ReducerCount = {{addReducers.Array.Length}}; public const int ProcedureCount = {{addProcedures.Array.Length}}; @@ -3120,6 +3164,8 @@ public readonly struct Tables { public readonly struct ReadOnlyTables { {{IndentGeneratedCode(string.Join("\n", readOnlyAccessors.Select(v => v.ReadOnlyGetter)), 12)}} } + + public readonly partial struct Queries { } } public static class LocalTableExtensions { extension(global::SpacetimeDB.Local db) { @@ -3133,6 +3179,11 @@ public static class ReadOnlyTableExtensions { {{IndentGeneratedCode(consumerReadOnlyAccessors, 12)}} } } + public static partial class QueryTableExtensions { + extension(global::SpacetimeDB.QueryBuilder from) { + {{IndentGeneratedCode(consumerQueryAccessors, 12)}} + } + } {{IndentGeneratedCode(queryBuilderExtensionMembers, 4)}} } #endif diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index 6a5679f86a7..123dac56ada 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -57,6 +57,10 @@ public static string ResolveName(string assemblyIdentity, string localName) => (namespaces ?? throw new InvalidOperationException("Module namespaces have not been installed.")) .Resolve(assemblyIdentity, localName); + public static SqlTableName ResolveSqlName(string assemblyIdentity, string localName) => + (namespaces ?? throw new InvalidOperationException("Module namespaces have not been installed.")) + .ResolveSqlName(assemblyIdentity, localName); + private static Func< Identity, ConnectionId?, diff --git a/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs b/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs index 510ec259168..a93b3006e70 100644 --- a/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs +++ b/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs @@ -19,9 +19,17 @@ public NamespaceRegistry(string rootIdentity, IEnumerable + private string? ResolveNamespace(string assemblyIdentity) => mounts.TryGetValue(assemblyIdentity, out var name) && !name.Equals("public", StringComparison.OrdinalIgnoreCase) - ? name + "." + localName - : localName; + ? name + : null; + + public string Resolve(string assemblyIdentity, string localName) => + ResolveNamespace(assemblyIdentity) is { } name ? name + "." + localName : localName; + + public SqlTableName ResolveSqlName(string assemblyIdentity, string localName) => + ResolveNamespace(assemblyIdentity) is { } name + ? new SqlTableName([name], localName) + : new SqlTableName(localName); } diff --git a/crates/testing/tests/standalone_integration_test.rs b/crates/testing/tests/standalone_integration_test.rs index c5dd49954d1..3da23c0948c 100644 --- a/crates/testing/tests/standalone_integration_test.rs +++ b/crates/testing/tests/standalone_integration_test.rs @@ -171,6 +171,10 @@ fn namespace_csharp_mounted_dependencies() { "SELECT * FROM extra_rows", "SELECT * FROM auth_data.users", "SELECT * FROM auth_data.anonymous_users", + "SELECT * FROM query_users", + "SELECT * FROM query_users_right", + "SELECT * FROM query_extra", + "SELECT * FROM auth_data.query_users", ] .map(Box::::from) .into(), @@ -186,7 +190,7 @@ fn namespace_csharp_mounted_dependencies() { message @ spacetimedb::client::messages::SerializableMessage::Subscribe(_), ) = message { - assert_eq!(message.num_rows(), Some(5)); + assert_eq!(message.num_rows(), Some(9)); return; } } diff --git a/modules/namespace-test-cs/Lib.cs b/modules/namespace-test-cs/Lib.cs index cdde9db4383..3a4b462624f 100644 --- a/modules/namespace-test-cs/Lib.cs +++ b/modules/namespace-test-cs/Lib.cs @@ -23,7 +23,7 @@ public static partial class Functions [Reducer] public static void Exercise(ReducerContext ctx) { - ctx.Db.User.Insert(new User { Id = 1 }); + ctx.Db.User.Insert(new User { Id = 2 }); AuthLib.Functions.Insert(ctx, 2); ctx.Db.MyAuth.User.Insert(new AuthLib.User { Id = 3, Score = 43 }); ctx.Db.@class.User.Insert(new AuditLib.User { Id = 4, Message = "consumer" }); @@ -49,7 +49,19 @@ public static ulong CountUsers(ProcedureContext ctx) => ctx.WithTx(tx => tx.Db.User.Count + tx.Db.MyAuth.User.Count + tx.Db.@class.User.Count); [View(Accessor = "Users", Public = true)] - public static User? Users(ViewContext ctx) => ctx.Db.User.Id.Find(1); + public static User? Users(ViewContext ctx) => ctx.Db.User.Id.Find(2); + + [View(Accessor = "QueryUsers", Public = true)] + public static IQuery QueryUsers(AnonymousViewContext ctx) => + ctx.From.User().LeftSemijoin(ctx.From.MyAuth.User(), (root, auth) => root.Id.Eq(auth.Id)); + + [View(Accessor = "QueryUsersRight", Public = true)] + public static IQuery QueryUsersRight(ViewContext ctx) => + AuthLib.Functions.Query(ctx).RightSemijoin(ctx.From.User(), (auth, root) => auth.Id.Eq(root.Id)); + + [View(Accessor = "QueryExtra", Public = true)] + public static IQuery QueryExtra(AnonymousViewContext ctx) => + ctx.From.ExtraRow().Where(row => row.Id.Eq(7u)); [View(Accessor = "AuthUsers", Public = true)] public static List AuthUsers(ViewContext ctx) => diff --git a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs index 5c4db70015e..dc325496899 100644 --- a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs +++ b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs @@ -22,6 +22,12 @@ public static void Insert(ReducerContext ctx, uint id) => public static ulong Count(ReducerContext ctx) => ctx.Db.User.Count; + public static FromWhere Query(ViewContext ctx) => + ctx.From.User().Where(row => row.Score.Eq(99u)); + + [View(Accessor = "QueryUsers", Public = true)] + public static IQuery QueryUsers(ViewContext ctx) => Query(ctx); + [Reducer] public static void Add(ReducerContext ctx, uint id) => Insert(ctx, id); diff --git a/sdks/csharp/tests~/QueryBuilderTests.cs b/sdks/csharp/tests~/QueryBuilderTests.cs index 8b531c3cadd..51913492b76 100644 --- a/sdks/csharp/tests~/QueryBuilderTests.cs +++ b/sdks/csharp/tests~/QueryBuilderTests.cs @@ -94,6 +94,45 @@ private static Table MakeRightTable(string tab new(tableName, new RightCols(tableName), new RightIxCols(tableName)); + [Fact] + public void QualifiedName_QuotesSegmentsAndCopiesInput() + { + var segments = new[] { "select", "we\"ird.namespace" }; + var name = new SqlTableName(segments, "users.with.dots"); + segments[0] = "changed"; + Assert.Equal(new[] { "select", "we\"ird.namespace" }, name.NamespaceSegments); + Assert.Equal("users.with.dots", name.LocalName); + Assert.Equal("\"select\".\"we\"\"ird.namespace\".\"users.with.dots\"", name.ToString()); + Assert.Throws(() => + ((System.Collections.Generic.IList)name.NamespaceSegments)[0] = "changed"); + Assert.Equal("SELECT * FROM \"auth.users\"", MakeTable("auth.users").ToSql()); + Assert.Equal("\"auth.users\".\"id\"", new Col("auth.users", "id").ToString()); + Assert.Equal("\"auth.users\".\"id\"", new IxCol("auth.users", "id").ToString()); + } + + [Fact] + public void QualifiedName_FiltersAndBothSemijoinsKeepSameLeafNamesDistinct() + { + var leftName = new SqlTableName(new[] { "auth" }, "users"); + var rightName = new SqlTableName(new[] { "audit" }, "users"); + var left = new Table, IxCol>( + leftName, new(leftName, "id"), new(leftName, "id")); + var right = new Table, IxCol>( + rightName, new(rightName, "id"), new(rightName, "id")); + Assert.Equal("SELECT * FROM \"auth\".\"users\" WHERE (\"auth\".\"users\".\"id\" = 1)", + left.Where(c => c.Eq(1)).ToSql()); + Assert.Equal("SELECT * FROM \"auth\".\"users\" WHERE (\"auth\".\"users\".\"id\" = 1)", + left.Where((_, ix) => ix.Eq(SqlLit.Int(1))).ToSql()); + const string join = " FROM \"auth\".\"users\" JOIN \"audit\".\"users\" ON \"auth\".\"users\".\"id\" = \"audit\".\"users\".\"id\""; + Assert.Equal("SELECT \"auth\".\"users\".*" + join, + left.LeftSemijoin(right, (l, r) => l.Eq(r)).ToSql()); + Assert.Equal("SELECT \"audit\".\"users\".*" + join, + left.RightSemijoin(right, (l, r) => l.Eq(r)).ToSql()); + var escaped = new SqlTableName(new[] { "auth\"data" }, "select"); + Assert.Equal("\"auth\"\"data\".\"select\".\"i\"\"d\"", new Col(escaped, "i\"d").ToString()); + Assert.Equal("\"auth\"\"data\".\"select\".\"i\"\"d\"", new IxCol(escaped, "i\"d").ToString()); + } + [Fact] public void All_QuotesTableName() { From a61fe514722507d8cf3fbd1ad8c7da7eece219ac Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Wed, 16 Sep 2026 15:59:03 -0500 Subject: [PATCH 09/49] Remove (maybe temporarily) the database Name and use Accessor everywhere --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 40 ++++++++++--------- crates/bindings-csharp/Codegen/Module.cs | 8 ++-- .../Codegen/NamespaceDeclaration.cs | 40 +++++++------------ crates/bindings-csharp/Runtime/Attrs.cs | 5 +-- .../tests/standalone_integration_test.rs | 15 +++---- modules/namespace-test-cs/Lib.cs | 4 +- 6 files changed, 49 insertions(+), 63 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index aa36c8fffc8..9e690cfa4eb 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -341,8 +341,8 @@ public partial struct Row { public uint Id; } } var auth = Dependency("Auth"); var audit = Dependency("Audit"); - string Mount(string marker = "Auth.Marker", string accessor = "MyAuth", string name = "auth_data") => - $"[assembly: SpacetimeDB.Namespace(typeof({marker}), Accessor = \"{accessor}\", Name = \"{name}\")]\n"; + string Mount(string marker = "Auth.Marker", string accessor = "MyAuth") => + $"[assembly: SpacetimeDB.Namespace(typeof({marker}), Accessor = \"{accessor}\")]\n"; GeneratorDriver Run(string source) => CSharpGeneratorDriver.Create( [new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions, @@ -367,7 +367,6 @@ object[] Parsed(GeneratorDriver driver) => [.. driver.GetRunResult().Results.Sin var driver = Run(Mount(accessor: accessor)); Assert.Empty(driver.GetRunResult().Diagnostics); var declaration = Assert.Single(Parsed(driver)); - Assert.Equal("auth_data", declaration.GetType().GetProperty("Name")!.GetValue(declaration)); Assert.Equal(accessor, declaration.GetType().GetProperty("Accessor")!.GetValue(declaration)); Assert.Equal( accessor == "MyAuth" ? accessor : "@" + accessor, @@ -378,22 +377,22 @@ object[] Parsed(GeneratorDriver driver) => [.. driver.GetRunResult().Results.Sin declaration.GetType().GetProperty("AssemblyIdentity")!.GetValue(declaration) ); } - Assert.Empty(Run(Mount(name: new string('a', 63))).GetRunResult().Diagnostics); - Assert.Empty(Run(Mount(name: "public")).GetRunResult().Diagnostics); - Reject(Mount(name: new string('a', 64)), "63 UTF-8 bytes"); + Assert.Empty(Run(Mount(accessor: new string('a', 63))).GetRunResult().Diagnostics); + Assert.Empty(Run(Mount(accessor: "public")).GetRunResult().Diagnostics); + Reject(Mount(accessor: new string('a', 64)), "63 UTF-8 bytes"); foreach (var name in new[] { "", "auth.data", "a-b", "1auth", " auth" }) - Reject(Mount(name: name), "database identifier"); + Reject(Mount(accessor: name), "database identifier"); foreach (var name in new[] { "st", "ST", "spacetimedb", "pg_catalog", "PG_temp" }) - Reject(Mount(name: name), "reserved"); + Reject(Mount(accessor: name), "reserved"); foreach (var accessor in new[] { "", "a.b", "a-b", "1auth", "@class", " auth" }) Reject(Mount(accessor: accessor), "C# identifier"); Reject("[assembly: SpacetimeDB.Namespace(typeof(Auth.Marker))]", "C# identifier"); Reject("[assembly: SpacetimeDB.Namespace(null)]", "marker type"); Reject(Mount("LocalMarker") + "public class LocalMarker { }", "cannot mount itself"); Reject(Mount("System.String"), "no discovered module descriptor"); - Reject(Mount() + Mount(accessor: "Other", name: "other"), "only be mounted once"); - Reject(Mount() + Mount("Audit.Marker", "Audit", "AUTH_DATA"), "case-insensitive"); - Reject(Mount() + Mount("Audit.Marker", "MyAuth", "audit_data"), "accessor 'MyAuth'"); + Reject(Mount() + Mount(accessor: "Other"), "only be mounted once"); + Reject(Mount() + Mount("Audit.Marker", "MYAUTH"), "case-insensitive"); + Reject(Mount() + Mount("Audit.Marker", "MyAuth"), "accessor 'MyAuth'"); Reject(Mount() + "[SpacetimeDB.Table(Accessor = \"MyAuth\")] public partial struct Row { public uint Id; }", "root table accessor"); @@ -408,9 +407,12 @@ [new Module().AsSourceGenerator()], parseOptions: oldLanguage // Only assembly targets are legal, independently of generator validation. var wrongTarget = Create("Consumer", "[SpacetimeDB.Namespace(typeof(Auth.Marker))] public class Wrong { }", auth); Assert.Contains(wrongTarget.GetDiagnostics(), d => d.Id == "CS0592"); + var obsoleteName = Create("Consumer", + "[assembly: SpacetimeDB.Namespace(typeof(Auth.Marker), Accessor = \"MyAuth\", Name = \"auth_data\")]", auth); + Assert.Contains(obsoleteName.GetDiagnostics(), d => d.Id == "CS0246"); var original = Run(Mount()); - foreach (var source in new[] { Mount(name: "other_data"), Mount(accessor: "Other") }) + foreach (var source in new[] { Mount(accessor: "Other"), Mount(accessor: "class") }) { var changed = original.RunGenerators(Create("Consumer", source, auth, audit)); Assert.Empty(changed.GetRunResult().Diagnostics); @@ -510,8 +512,8 @@ MethodDeclarationSyntax Method(CSharpCompilation compilation, string name) => As "public class UtilityLink { public Shared.Sentinel Value; }", shared)); var rootSource = rootHasTable ? Table("Root") : ""; if (mounted) - rootSource = "[assembly: SpacetimeDB.Namespace(typeof(Alpha.Sentinel), Accessor = \"Auth\", Name = \"auth_data\")]\n" - + "[assembly: SpacetimeDB.Namespace(typeof(Beta.Sentinel), Accessor = \"class\", Name = \"audit_data\")]\n" + rootSource = "[assembly: SpacetimeDB.Namespace(typeof(Alpha.Sentinel), Accessor = \"Auth\")]\n" + + "[assembly: SpacetimeDB.Namespace(typeof(Beta.Sentinel), Accessor = \"class\")]\n" + rootSource + "public static class Helpers { public static ulong Count(SpacetimeDB.ReducerContext ctx) => ctx.Db.Auth.AlphaRow.Count + ctx.Db.@class.BetaRow.Count + ctx.Db.SharedRow.Count; }"; rootSource += $$""" @@ -541,7 +543,7 @@ [.. Method(compilation, "Initialize").DescendantNodes() var init = Method(root, "Initialize"); var submodules = init.DescendantNodes().OfType() .Where(call => call.Expression.ToString().EndsWith(".RegisterSubmodule")).ToArray(); - Assert.Equal(["\"auth_data\"", "\"audit_data\""], + Assert.Equal(["\"Auth\"", "\"class\""], submodules.Select(call => call.ArgumentList.Arguments[0].ToString())); var invalid = root.AddSyntaxTrees(CSharpSyntaxTree.ParseText( "public static class BadView { public static void Write(SpacetimeDB.ViewContext ctx) => ctx.Db.Auth.AlphaRow.Insert(new Alpha.AlphaRow()); }", @@ -585,7 +587,7 @@ [.. Method(compilation, "Initialize").DescendantNodes() Assert.Empty(empty.GetSymbolsWithName("AssemblyDescriptor", SymbolFilter.Type)); var nested = Emit(Generate(Create("Nested", - "[assembly: SpacetimeDB.Namespace(typeof(Alpha.Sentinel), Accessor = \"Auth\", Name = \"auth_data\")]", + "[assembly: SpacetimeDB.Namespace(typeof(Alpha.Sentinel), Accessor = \"Auth\")]", alpha, shared))); var nestedResult = CSharpGeneratorDriver.Create( [new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions @@ -605,15 +607,15 @@ public static void Handle(SpacetimeDB.ReducerContext ctx) { } var lifecycleResult = CSharpGeneratorDriver.Create( [new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions ).RunGenerators(Create("LifecycleConsumer", - "[assembly: SpacetimeDB.Namespace(typeof(Marker), Accessor = \"Auth\", Name = \"auth_data\")]", + "[assembly: SpacetimeDB.Namespace(typeof(Marker), Accessor = \"Auth\")]", lifecycle)).GetRunResult(); Assert.Contains(lifecycleResult.Diagnostics, diagnostic => diagnostic.GetMessage().Contains("LifecycleFunctions.Handle (" + kind + ")") - && diagnostic.GetMessage().Contains("auth_data")); + && diagnostic.GetMessage().Contains("Auth")); // The same dependency can still be published alone or merged into the root scope. Generate(Create("FlatLifecycleConsumer", "", lifecycle)); Generate(Create("PublicLifecycleConsumer", - "[assembly: SpacetimeDB.Namespace(typeof(Marker), Accessor = \"Auth\", Name = \"public\")]", + "[assembly: SpacetimeDB.Namespace(typeof(Marker), Accessor = \"public\")]", lifecycle)); } } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 618529c01e0..42a3ccf9af7 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -2616,7 +2616,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .ToDictionary(m => m.AssemblyIdentity, StringComparer.Ordinal); bool IsChild(AssemblyDeclaration assembly) => mountByIdentity.TryGetValue(assembly.Identity, out var mount) - && !mount.Name.Equals("public", StringComparison.OrdinalIgnoreCase); + && !mount.Accessor.Equals("public", StringComparison.OrdinalIgnoreCase); var unmountedAssemblies = assemblies.Where(a => !IsChild(a)).ToArray(); var mountedAssemblies = assemblies.Where(IsChild).ToArray(); var registrationOrder = unmountedAssemblies.Concat(mountedAssemblies).ToArray(); @@ -2624,7 +2624,7 @@ bool IsChild(AssemblyDeclaration assembly) => context.ReportDiagnostic(ErrorDescriptor.DependencyNamespaceMounts.ToDiag(assembly.Identity)); foreach (var assembly in mountedAssemblies.Where(a => a.LifecycleReducers.Length != 0)) context.ReportDiagnostic(ErrorDescriptor.MountedLifecycleReducers.ToDiag( - (assembly.Identity, mountByIdentity[assembly.Identity].Name, assembly.LifecycleReducers))); + (assembly.Identity, mountByIdentity[assembly.Identity].Accessor, assembly.LifecycleReducers))); string GenerateDispatchRouting(string category, string arguments, string unknownId) { @@ -2704,7 +2704,7 @@ void Add(string name, string owner, string declaration) "global::SpacetimeDB.Internal.Module.InstallNamespaces(new global::SpacetimeDB.Internal.NamespaceRegistry(" + SymbolDisplay.FormatLiteral(assemblyContext.Identity, true) + ", new global::System.Collections.Generic.KeyValuePair[] {" + string.Join(",", mountByIdentity.Values.Select(m => - $"new({SymbolDisplay.FormatLiteral(m.AssemblyIdentity, true)}, {SymbolDisplay.FormatLiteral(m.Name, true)})")) + "}));", + $"new({SymbolDisplay.FormatLiteral(m.AssemblyIdentity, true)}, {SymbolDisplay.FormatLiteral(m.Accessor, true)})")) + "}));", $"global::{extensionNamespaceName}.AssemblyDescriptor.Register(global::SpacetimeDB.Internal.Module.RootBuilder);" }; foreach (var assembly in unmountedAssemblies) @@ -2714,7 +2714,7 @@ void Add(string name, string owner, string declaration) var assembly = mountedAssemblies[i]; compositionRegistration.Add($"var child{i} = new global::SpacetimeDB.Internal.ModuleBuilder();"); compositionRegistration.Add($"{assembly.DescriptorTypeName}.Register(child{i}, global::SpacetimeDB.Internal.Module.RootBuilder);"); - compositionRegistration.Add($"global::SpacetimeDB.Internal.Module.RootBuilder.RegisterSubmodule({SymbolDisplay.FormatLiteral(mountByIdentity[assembly.Identity].Name, true)}, child{i});"); + compositionRegistration.Add($"global::SpacetimeDB.Internal.Module.RootBuilder.RegisterSubmodule({SymbolDisplay.FormatLiteral(mountByIdentity[assembly.Identity].Accessor, true)}, child{i});"); } if (settings.Array.Length > 1) diff --git a/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs b/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs index dcf1e26d419..7937d8fbb00 100644 --- a/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs +++ b/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs @@ -6,7 +6,7 @@ namespace SpacetimeDB.Codegen; using Microsoft.CodeAnalysis.CSharp; using static Utils; -record NamespaceDeclaration(string AssemblyIdentity, string Accessor, string Name) +record NamespaceDeclaration(string AssemblyIdentity, string Accessor) { public string AccessorIdentifier => EscapeIdentifier(Accessor); @@ -23,8 +23,7 @@ CancellationToken cancellationToken if (attributeType is null) return new(result.ToImmutable()); var identities = new Dictionary(StringComparer.Ordinal); - var names = new Dictionary(StringComparer.OrdinalIgnoreCase); - var accessors = new Dictionary(StringComparer.Ordinal); + var accessors = new Dictionary(StringComparer.OrdinalIgnoreCase); var tables = new HashSet(tableAccessors, StringComparer.Ordinal); var supported = compilation.SyntaxTrees.Any(tree => tree.Options is CSharpParseOptions options @@ -73,9 +72,6 @@ void Error(string message) attribute.NamedArguments.FirstOrDefault(a => a.Key == "Accessor").Value.Value as string ?? ""; - var name = - attribute.NamedArguments.FirstOrDefault(a => a.Key == "Name").Value.Value as string - ?? ""; // Keywords are stored unescaped and escaped only when rendering C#. if ( accessor.Length == 0 @@ -88,25 +84,25 @@ as string ) Error("Accessor must be a nonempty C# identifier (use keyword names without '@')."); - // Keep database names separate from C# identifier/keyword rules. + // The accessor is also the database namespace, so both sets of rules apply. // The host remains authoritative for full Unicode identifier validation. if ( - name.Length == 0 - || !(char.IsLetter(name[0]) || name[0] == '_') - || name.Any(c => !(char.IsLetterOrDigit(c) || c == '_')) - || !name.IsNormalized(NormalizationForm.FormC) + accessor.Length == 0 + || !(char.IsLetter(accessor[0]) || accessor[0] == '_') + || accessor.Any(c => !(char.IsLetterOrDigit(c) || c == '_')) + || !accessor.IsNormalized(NormalizationForm.FormC) ) Error( - "Name must be a nonempty database identifier: letters, digits or underscores, starting with a letter or underscore." + "Accessor must also be a nonempty database identifier: letters, digits or underscores, starting with a letter or underscore." ); - if (Encoding.UTF8.GetByteCount(name) > 63) + if (Encoding.UTF8.GetByteCount(accessor) > 63) Error("Namespace names cannot exceed 63 UTF-8 bytes (the current host limit)."); if ( - name.Equals("st", StringComparison.OrdinalIgnoreCase) - || name.Equals("spacetimedb", StringComparison.OrdinalIgnoreCase) - || name.StartsWith("pg_", StringComparison.OrdinalIgnoreCase) + accessor.Equals("st", StringComparison.OrdinalIgnoreCase) + || accessor.Equals("spacetimedb", StringComparison.OrdinalIgnoreCase) + || accessor.StartsWith("pg_", StringComparison.OrdinalIgnoreCase) ) - Error($"Namespace '{name}' is reserved."); + Error($"Namespace '{accessor}' is reserved."); void CheckDuplicate(Dictionary seen, string key, string message) { @@ -124,23 +120,17 @@ void CheckDuplicate(Dictionary seen, string key, string m identity, $"Assembly '{identity}' may only be mounted once." ); - if (name.Length > 0) - CheckDuplicate( - names, - name, - $"Namespace '{name}' is declared more than once (case-insensitive)." - ); if (accessor.Length > 0) CheckDuplicate( accessors, accessor, - $"Namespace accessor '{accessor}' is declared more than once." + $"Namespace accessor '{accessor}' is declared more than once (case-insensitive)." ); if (tables.Contains(accessor)) Error($"Namespace accessor '{accessor}' conflicts with a root table accessor."); if (valid) - result.Add(new(identity, accessor, name)); + result.Add(new(identity, accessor)); } return new(result.ToImmutable()); } diff --git a/crates/bindings-csharp/Runtime/Attrs.cs b/crates/bindings-csharp/Runtime/Attrs.cs index 121b8be9391..aaa83f23113 100644 --- a/crates/bindings-csharp/Runtime/Attrs.cs +++ b/crates/bindings-csharp/Runtime/Attrs.cs @@ -11,11 +11,8 @@ public sealed class NamespaceAttribute(System.Type marker) : Attribute { public System.Type Marker { get; } = marker; - /// The C# member name used to access the mounted module. + /// The C# member name and database namespace used for the mounted module. public string Accessor { get; set; } = ""; - - /// The database namespace, independent of the C# accessor. - public string Name { get; set; } = ""; } #endif diff --git a/crates/testing/tests/standalone_integration_test.rs b/crates/testing/tests/standalone_integration_test.rs index 3da23c0948c..0ffe309d9ac 100644 --- a/crates/testing/tests/standalone_integration_test.rs +++ b/crates/testing/tests/standalone_integration_test.rs @@ -142,18 +142,15 @@ fn namespace_csharp_mounted_dependencies() { module.call_reducer_binary("exercise", &product![]).await.unwrap(); assert!(module.read_log(None).await.contains("namespace composition works")); module - .call_reducer_binary("auth_data.add", &product![10u32]) - .await - .unwrap(); - module - .call_reducer_binary("audit_data.add", &product![11u32]) + .call_reducer_binary("MyAuth.add", &product![10u32]) .await .unwrap(); + module.call_reducer_binary("class.add", &product![11u32]).await.unwrap(); assert_eq!( module.call_procedure_with_args("count_users", "[]").await.unwrap(), AlgebraicValue::U64(5) ); - for name in ["auth_data.count_users", "audit_data.count_users"] { + for name in ["MyAuth.count_users", "class.count_users"] { assert_eq!( module.call_procedure_with_args(name, "[]").await.unwrap(), AlgebraicValue::U64(2) @@ -169,12 +166,12 @@ fn namespace_csharp_mounted_dependencies() { "SELECT * FROM users", "SELECT * FROM auth_users", "SELECT * FROM extra_rows", - "SELECT * FROM auth_data.users", - "SELECT * FROM auth_data.anonymous_users", + "SELECT * FROM \"MyAuth\".users", + "SELECT * FROM \"MyAuth\".anonymous_users", "SELECT * FROM query_users", "SELECT * FROM query_users_right", "SELECT * FROM query_extra", - "SELECT * FROM auth_data.query_users", + "SELECT * FROM \"MyAuth\".query_users", ] .map(Box::::from) .into(), diff --git a/modules/namespace-test-cs/Lib.cs b/modules/namespace-test-cs/Lib.cs index 3a4b462624f..555eb6b8f95 100644 --- a/modules/namespace-test-cs/Lib.cs +++ b/modules/namespace-test-cs/Lib.cs @@ -1,7 +1,7 @@ using SpacetimeDB; -[assembly: Namespace(typeof(AuthLib.Marker), Accessor = "MyAuth", Name = "auth_data")] -[assembly: Namespace(typeof(AuditLib.Marker), Accessor = "class", Name = "audit_data")] +[assembly: Namespace(typeof(AuthLib.Marker), Accessor = "MyAuth")] +[assembly: Namespace(typeof(AuditLib.Marker), Accessor = "class")] namespace NamespaceRoot; From 08c33fbe827a56fea79a14248d0656bbdcca7018 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 17 Sep 2026 10:45:57 -0500 Subject: [PATCH 10/49] Add SDK side --- Cargo.lock | 1 + .../SpacetimeSharpSATS.sln.DotSettings.user | 2 + crates/codegen/Cargo.toml | 1 + crates/codegen/src/csharp.rs | 392 +++++++++++++++--- crates/codegen/tests/codegen.rs | 220 +++++++++- .../tests/csharp-namespaces/Program.cs | 166 ++++++++ sdks/csharp/DEVELOP.md | 16 +- sdks/csharp/src/Table.cs | 5 +- 8 files changed, 745 insertions(+), 58 deletions(-) create mode 100644 crates/bindings-csharp/SpacetimeSharpSATS.sln.DotSettings.user create mode 100644 crates/codegen/tests/csharp-namespaces/Program.cs diff --git a/Cargo.lock b/Cargo.lock index a13e6d9b3a2..7213d62f0b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8160,6 +8160,7 @@ dependencies = [ "spacetimedb-primitives", "spacetimedb-schema", "spacetimedb-testing", + "tempfile", ] [[package]] diff --git a/crates/bindings-csharp/SpacetimeSharpSATS.sln.DotSettings.user b/crates/bindings-csharp/SpacetimeSharpSATS.sln.DotSettings.user new file mode 100644 index 00000000000..a29253dede0 --- /dev/null +++ b/crates/bindings-csharp/SpacetimeSharpSATS.sln.DotSettings.user @@ -0,0 +1,2 @@ + + ForceIncluded \ No newline at end of file diff --git a/crates/codegen/Cargo.toml b/crates/codegen/Cargo.toml index 9d362a09ade..afb6ab6968e 100644 --- a/crates/codegen/Cargo.toml +++ b/crates/codegen/Cargo.toml @@ -21,6 +21,7 @@ serde_json.workspace = true fs-err.workspace = true insta.workspace = true regex.workspace = true +tempfile.workspace = true spacetimedb-testing = { path = "../testing" } [lints] diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs index 931bf205484..66e316b1f29 100644 --- a/crates/codegen/src/csharp.rs +++ b/crates/codegen/src/csharp.rs @@ -15,8 +15,10 @@ use crate::{indent_scope, CodegenOptions, OutputFile}; use convert_case::{Case, Casing}; use spacetimedb_lib::sats::layout::PrimitiveType; use spacetimedb_primitives::ColId; -use spacetimedb_schema::def::{BTreeAlgorithm, IndexAlgorithm, ModuleDef, TableDef, TypeDef}; -use spacetimedb_schema::identifier::Identifier; +use spacetimedb_schema::def::{ + BTreeAlgorithm, IndexAlgorithm, ModuleDef, ProcedureDef, ReducerDef, TableDef, TypeDef, ViewDef, +}; +use spacetimedb_schema::identifier::{Identifier, NamespacePath}; use spacetimedb_schema::schema::TableSchema; use spacetimedb_schema::type_for_generate::{ AlgebraicTypeDef, AlgebraicTypeUse, PlainEnumTypeDef, ProductTypeDef, SumTypeDef, TypespaceForGenerate, @@ -503,9 +505,245 @@ pub struct Csharp<'opts> { } impl Lang for Csharp<'_> { + fn generate_table_file_from_schema(&self, module: &ModuleDef, table: &TableDef, schema: TableSchema) -> OutputFile { + self.scope(NamespacePath::root()) + .generate_table_file_from_schema(module, table, schema) + } + + fn generate_type_files(&self, module: &ModuleDef, typ: &TypeDef) -> Vec { + self.scope(NamespacePath::root()).generate_type_files(module, typ) + } + + fn generate_reducer_file(&self, module: &ModuleDef, reducer: &ReducerDef) -> OutputFile { + self.scope(NamespacePath::root()).generate_reducer_file(module, reducer) + } + + fn generate_procedure_file(&self, module: &ModuleDef, procedure: &ProcedureDef) -> OutputFile { + self.scope(NamespacePath::root()) + .generate_procedure_file(module, procedure) + } + + fn generate_submodule_table_file(&self, module: &ModuleDef, path: &NamespacePath, table: &TableDef) -> OutputFile { + scoped_file(path, self.scope(path.clone()).generate_table_file(module, table)) + } + + fn generate_submodule_view_file(&self, module: &ModuleDef, path: &NamespacePath, view: &ViewDef) -> OutputFile { + scoped_file(path, self.scope(path.clone()).generate_view_file(module, view)) + } + + fn generate_submodule_reducer_file( + &self, + module: &ModuleDef, + path: &NamespacePath, + reducer: &ReducerDef, + ) -> OutputFile { + scoped_file(path, self.scope(path.clone()).generate_reducer_file(module, reducer)) + } + + fn generate_submodule_procedure_file( + &self, + module: &ModuleDef, + path: &NamespacePath, + procedure: &ProcedureDef, + ) -> OutputFile { + scoped_file( + path, + self.scope(path.clone()).generate_procedure_file(module, procedure), + ) + } + + fn generate_global_files(&self, module: &ModuleDef, options: &CodegenOptions) -> Vec { + let mut files = self.scope(NamespacePath::root()).generate_global_files(module, options); + self.child_files(module, &NamespacePath::root(), &mut files); + files + } +} + +impl Csharp<'_> { + fn scope(&self, path: NamespacePath) -> CsharpScope<'_> { + let namespace = clr_namespace(self.namespace, &path); + CsharpScope { + namespace, + root_namespace: self.namespace, + path, + } + } + + fn child_files(&self, module: &ModuleDef, path: &NamespacePath, files: &mut Vec) { + for (name, child) in module.submodules() { + let path = path.child(name.clone()); + let scope = self.scope(path.clone()); + // Child typespaces are independent, including types used only by functions. + for typ in child.types() { + files.extend( + scope + .generate_type_files(child, typ) + .into_iter() + .map(|file| scoped_file(&path, file)), + ); + } + files.push(scoped_file(&path, scope.child_globals(child))); + self.child_files(child, &path, files); + } + } +} + +struct CsharpScope<'a> { + namespace: String, + root_namespace: &'a str, + path: NamespacePath, +} + +fn scoped_file(path: &NamespacePath, mut file: OutputFile) -> OutputFile { + file.filename = format!("{}/{}", path.join_segments("/"), file.filename); + file +} + +fn clr_namespace(root: &str, path: &NamespacePath) -> String { + let mut namespace = root.to_owned(); + for segment in path.segments() { + // Keep namespace accessors verbatim; @ also handles keyword identifiers. + write!(namespace, ".@{segment}").unwrap(); + } + namespace +} + +fn member_path(path: &NamespacePath) -> String { + path.segments().iter().map(|segment| format!("@{segment}.")).collect() +} + +impl CsharpScope<'_> { + fn root_type(&self, name: &str) -> String { + if self.path.is_empty() { + name.to_owned() + } else { + format!("global::{}.{name}", self.root_namespace) + } + } + + fn sql_name(&self, name: &Identifier) -> String { + let segments = self + .path + .segments() + .iter() + .map(|s| format!("{s:?}")) + .collect::>() + .join(", "); + format!( + "new global::SpacetimeDB.SqlTableName(new string[] {{ {segments} }}, {:?})", + name.deref() + ) + } + + fn child_members(&self, output: &mut CodeIndenter, module: &ModuleDef, container: &str) { + for name in module.submodules().keys() { + let namespace = clr_namespace(self.root_namespace, &self.path.child(name.clone())); + if container == "From" { + writeln!(output, "public global::{namespace}.From @{name} {{ get; }} = new();"); + } else { + writeln!(output, "public global::{namespace}.{container} @{name} {{ get; }}"); + } + } + } + + fn function_container(&self, output: &mut CodeIndenter, module: &ModuleDef, container: &str) { + writeln!(output, "public sealed partial class {container} : RemoteBase"); + indented_block(output, |output| { + self.child_members(output, module, container); + let conn = self.root_type("DbConnection"); + if module.submodules().is_empty() { + writeln!(output, "internal {container}({conn} conn) : base(conn) {{ }}"); + } else { + writeln!(output, "internal {container}({conn} conn) : base(conn)"); + indented_block(output, |output| { + for name in module.submodules().keys() { + writeln!(output, "@{name} = new(conn);"); + if container == "RemoteReducers" { + writeln!(output, "@{name}.InternalOnUnhandledReducerError += (ctx, error) => InternalOnUnhandledReducerError?.Invoke(ctx, error);"); + } + } + }); + } + if container == "RemoteReducers" { + let context = self.root_type("ReducerEventContext"); + if !self.path.is_empty() + && module.submodules().is_empty() + && iter_reducers(module, crate::CodegenVisibility::OnlyPublic) + .next() + .is_none() + { + // An empty namespace cannot raise an error; avoid an unused backing event. + writeln!(output, "internal event Action<{context}, Exception>? InternalOnUnhandledReducerError {{ add {{ }} remove {{ }} }}"); + } else { + writeln!( + output, + "internal event Action<{context}, Exception>? InternalOnUnhandledReducerError;" + ); + } + } + }); + writeln!(output); + } + + fn from(&self, output: &mut CodeIndenter, module: &ModuleDef, options: &CodegenOptions) { + writeln!(output, "public sealed class From"); + indented_block(output, |output| { + self.child_members(output, module, "From"); + for (name, accessor_name, product_type_ref) in iter_table_names_and_types(module, options.visibility) { + let method_name = accessor_name.deref().to_case(Case::Pascal); + let row_type = type_ref_name(module, product_type_ref); + let table_name_lit = if self.path.is_empty() { + format!("{:?}", name.deref()) + } else { + self.sql_name(name) + }; + writeln!(output, "public global::SpacetimeDB.Table<{row_type}, {method_name}Cols, {method_name}IxCols> {method_name}() => new({table_name_lit}, new {method_name}Cols({table_name_lit}), new {method_name}IxCols({table_name_lit}));"); + } + }); + writeln!(output); + } + + fn child_globals(&self, module: &ModuleDef) -> OutputFile { + let mut output = CsharpAutogen::new(&self.namespace, &["System.Collections.Generic"], false); + self.function_container(&mut output, module, "RemoteReducers"); + self.function_container(&mut output, module, "RemoteProcedures"); + writeln!(output, "public sealed partial class RemoteTables"); + indented_block(&mut output, |output| { + self.child_members(output, module, "RemoteTables"); + writeln!( + output, + "internal RemoteTables(global::{}.DbConnection conn, Action register)", + self.root_namespace + ); + indented_block(output, |output| { + for (_, accessor, _) in iter_table_names_and_types(module, crate::CodegenVisibility::OnlyPublic) { + writeln!( + output, + "register({} = new(conn));", + accessor.deref().to_case(Case::Pascal) + ); + } + for name in module.submodules().keys() { + writeln!(output, "@{name} = new(conn, register);"); + } + }); + }); + self.from(&mut output, module, &CodegenOptions::default()); + writeln!(output, "public abstract partial class Reducer"); + indented_block(&mut output, |output| writeln!(output, "private Reducer() {{ }}")); + writeln!(output, "public abstract partial class Procedure"); + indented_block(&mut output, |output| writeln!(output, "private Procedure() {{ }}")); + OutputFile { + filename: "Namespace.g.cs".to_owned(), + code: output.into_inner(), + } + } +} + +impl Lang for CsharpScope<'_> { fn generate_table_file_from_schema(&self, module: &ModuleDef, table: &TableDef, schema: TableSchema) -> OutputFile { let mut output = CsharpAutogen::new( - self.namespace, + &self.namespace, &[ "SpacetimeDB.BSATN", "SpacetimeDB.ClientApi", @@ -520,6 +758,7 @@ impl Lang for Csharp<'_> { let csharp_table_name = table.accessor_name.deref().to_case(Case::Pascal); let csharp_table_class_name = csharp_table_name.clone() + "Handle"; let table_type = type_ref_name(module, table.product_type_ref); + let context = self.root_type("EventContext"); let base_class = if table.is_event { "RemoteEventTableHandle" @@ -528,10 +767,21 @@ impl Lang for Csharp<'_> { }; writeln!( output, - "public sealed class {csharp_table_class_name} : {base_class}" + "public sealed class {csharp_table_class_name} : {base_class}<{context}, {table_type}>" ); indented_block(output, |output| { - writeln!(output, "public override string RemoteTableName => \"{}\";", table.name); + writeln!( + output, + "public override string RemoteTableName => \"{}{}\";", + self.path, table.name + ); + if !self.path.is_empty() { + writeln!( + output, + "protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => {};", + self.sql_name(&table.name) + ); + } writeln!(output); // If this is a table, we want to generate event accessor and indexes @@ -679,9 +929,10 @@ impl Lang for Csharp<'_> { ); } + let connection = self.root_type("DbConnection"); writeln!( output, - "internal {csharp_table_class_name}(DbConnection conn) : base(conn)" + "internal {csharp_table_class_name}({connection} conn) : base(conn)" ); indented_block(output, |output| { for csharp_index_name in &index_names { @@ -741,7 +992,12 @@ impl Lang for Csharp<'_> { ); } writeln!(output); - writeln!(output, "public {cols_owner_name}Cols(string tableName)"); + let name_type = if self.path.is_empty() { + "string" + } else { + "global::SpacetimeDB.SqlTableName" + }; + writeln!(output, "public {cols_owner_name}Cols({name_type} tableName)"); indented_block(output, |output| { for (field_name, field_type) in &product_type.elements { let prop = field_name.deref().to_case(Case::Pascal); @@ -776,7 +1032,12 @@ impl Lang for Csharp<'_> { ); } writeln!(output); - writeln!(output, "public {cols_owner_name}IxCols(string tableName)"); + let name_type = if self.path.is_empty() { + "string" + } else { + "global::SpacetimeDB.SqlTableName" + }; + writeln!(output, "public {cols_owner_name}IxCols({name_type} tableName)"); indented_block(output, |output| { for (i, (field_name, field_type)) in product_type.elements.iter().enumerate() { if !ix_col_positions.contains(&i) { @@ -806,10 +1067,10 @@ impl Lang for Csharp<'_> { let name = collect_case(Case::Pascal, typ.accessor_name.name_segments()); let filename = format!("Types/{name}.g.cs"); let code = match &module.typespace_for_generate()[typ.ty] { - AlgebraicTypeDef::Sum(sum) => autogen_csharp_sum(module, name.clone(), sum, self.namespace), - AlgebraicTypeDef::Product(prod) => autogen_csharp_tuple(module, name.clone(), prod, self.namespace), + AlgebraicTypeDef::Sum(sum) => autogen_csharp_sum(module, name.clone(), sum, &self.namespace), + AlgebraicTypeDef::Product(prod) => autogen_csharp_tuple(module, name.clone(), prod, &self.namespace), AlgebraicTypeDef::PlainEnum(plain_enum) => { - autogen_csharp_plain_enum(name.clone(), plain_enum, self.namespace) + autogen_csharp_plain_enum(name.clone(), plain_enum, &self.namespace) } }; @@ -818,7 +1079,7 @@ impl Lang for Csharp<'_> { fn generate_reducer_file(&self, module: &ModuleDef, reducer: &spacetimedb_schema::def::ReducerDef) -> OutputFile { let mut output = CsharpAutogen::new( - self.namespace, + &self.namespace, &[ "SpacetimeDB.ClientApi", "System.Collections.Generic", @@ -829,6 +1090,7 @@ impl Lang for Csharp<'_> { writeln!(output, "public sealed partial class RemoteReducers : RemoteBase"); indented_block(&mut output, |output| { + let context = self.root_type("ReducerEventContext"); let func_name_pascal_case = reducer.accessor_name.deref().to_case(Case::Pascal); let delegate_separator = if reducer.params_for_generate.elements.is_empty() { "" @@ -837,11 +1099,11 @@ impl Lang for Csharp<'_> { }; let (func_params, func_args) = - build_func_params_and_args(module, reducer.params_for_generate.into_iter(), self.namespace); + build_func_params_and_args(module, reducer.params_for_generate.into_iter(), &self.namespace); writeln!( output, - "public delegate void {func_name_pascal_case}Handler(ReducerEventContext ctx{delegate_separator}{func_params});" + "public delegate void {func_name_pascal_case}Handler({context} ctx{delegate_separator}{func_params});" ); writeln!( output, @@ -862,7 +1124,7 @@ impl Lang for Csharp<'_> { writeln!( output, - "public bool Invoke{func_name_pascal_case}(ReducerEventContext ctx, Reducer.{func_name_pascal_case} args)" + "public bool Invoke{func_name_pascal_case}({context} ctx, Reducer.{func_name_pascal_case} args)" ); indented_block(output, |output| { writeln!(output, "if (On{func_name_pascal_case} == null)"); @@ -899,12 +1161,17 @@ impl Lang for Csharp<'_> { writeln!(output, "public abstract partial class Reducer"); indented_block(&mut output, |output| { + let base_type = if self.path.is_empty() { + "Reducer, IReducerArgs".to_owned() + } else { + format!("global::{}.Reducer, IReducerArgs", self.root_namespace) + }; autogen_csharp_product_common( module, output, reducer.accessor_name.deref().to_case(Case::Pascal), &reducer.params_for_generate, - "Reducer, IReducerArgs", + &base_type, |output| { if !reducer.params_for_generate.elements.is_empty() { writeln!(output); @@ -926,7 +1193,7 @@ impl Lang for Csharp<'_> { procedure: &spacetimedb_schema::def::ProcedureDef, ) -> OutputFile { let mut output = CsharpAutogen::new( - self.namespace, + &self.namespace, &[ "SpacetimeDB.ClientApi", "System.Collections.Generic", @@ -945,8 +1212,8 @@ impl Lang for Csharp<'_> { }; let (func_params, func_args) = - build_func_params_and_args(module, procedure.params_for_generate.into_iter(), self.namespace); - let return_type_str = ty_fmt_with_ns(module, &procedure.return_type_for_generate, self.namespace); + build_func_params_and_args(module, procedure.params_for_generate.into_iter(), &self.namespace); + let return_type_str = ty_fmt_with_ns(module, &procedure.return_type_for_generate, &self.namespace); // Generate the clean public API that users call to allow us of BSATN.Decode<> then reflect to the proper return type writeln!( output, @@ -1000,7 +1267,7 @@ impl Lang for Csharp<'_> { output, procedure.accessor_name.deref().to_case(Case::Pascal).to_string(), &procedure.return_type_for_generate, - self.namespace, + &self.namespace, ); autogen_csharp_product_common( module, @@ -1012,7 +1279,11 @@ impl Lang for Csharp<'_> { if !procedure.params_for_generate.elements.is_empty() { writeln!(output); } - writeln!(output, "string IProcedureArgs.ProcedureName => \"{}\";", procedure.name); + writeln!( + output, + "string IProcedureArgs.ProcedureName => \"{}{}\";", + self.path, procedure.name + ); }, ); writeln!(output); @@ -1029,7 +1300,7 @@ impl Lang for Csharp<'_> { fn generate_global_files(&self, module: &ModuleDef, options: &CodegenOptions) -> Vec { let mut output = CsharpAutogen::new( - self.namespace, + &self.namespace, &[ "SpacetimeDB.ClientApi", "System.Collections.Generic", @@ -1038,27 +1309,12 @@ impl Lang for Csharp<'_> { true, // print the version in the globals file ); - writeln!(output, "public sealed partial class RemoteReducers : RemoteBase"); - indented_block(&mut output, |output| { - writeln!(output, "internal RemoteReducers(DbConnection conn) : base(conn) {{ }}"); - writeln!( - output, - "internal event Action? InternalOnUnhandledReducerError;" - ) - }); - writeln!(output); - - writeln!(output, "public sealed partial class RemoteProcedures : RemoteBase"); - indented_block(&mut output, |output| { - writeln!( - output, - "internal RemoteProcedures(DbConnection conn) : base(conn) {{ }}" - ); - }); - writeln!(output); + self.function_container(&mut output, module, "RemoteReducers"); + self.function_container(&mut output, module, "RemoteProcedures"); writeln!(output, "public sealed partial class RemoteTables : RemoteTablesBase"); indented_block(&mut output, |output| { + self.child_members(output, module, "RemoteTables"); writeln!(output, "public RemoteTables(DbConnection conn)"); indented_block(output, |output| { for (_, accessor_name, _) in iter_table_names_and_types(module, options.visibility) { @@ -1068,6 +1324,9 @@ impl Lang for Csharp<'_> { accessor_name.deref().to_case(Case::Pascal) ); } + for name in module.submodules().keys() { + writeln!(output, "@{name} = new(conn, AddTable);"); + } }); }); writeln!(output); @@ -1084,24 +1343,34 @@ impl Lang for Csharp<'_> { let method_name = accessor_name.deref().to_case(Case::Pascal); writeln!(output, "new QueryBuilder().From.{method_name}().ToSql(),"); } + for (path, _, table) in module.all_tables_with_prefix().into_iter().filter(|(path, _, table)| { + !path.is_empty() && table.table_access == spacetimedb_lib::db::raw_def::v9::TableAccess::Public + }) { + writeln!( + output, + "new QueryBuilder().From.{}{}().ToSql(),", + member_path(&path), + table.accessor_name.deref().to_case(Case::Pascal) + ); + } + for (path, _, view) in module + .all_views_with_prefix() + .into_iter() + .filter(|(path, _, _)| !path.is_empty()) + { + writeln!( + output, + "new QueryBuilder().From.{}{}().ToSql(),", + member_path(&path), + view.accessor_name.deref().to_case(Case::Pascal) + ); + } }); writeln!(output, ";"); }); writeln!(output); - writeln!(output, "public sealed class From"); - indented_block(&mut output, |output| { - for (name, accessor_name, product_type_ref) in iter_table_names_and_types(module, options.visibility) { - let method_name = accessor_name.deref().to_case(Case::Pascal); - let row_type = type_ref_name(module, product_type_ref); - let table_name_lit = format!("{:?}", name.deref()); - writeln!( - output, - "public global::SpacetimeDB.Table<{row_type}, {method_name}Cols, {method_name}IxCols> {method_name}() => new({table_name_lit}, new {method_name}Cols({table_name_lit}), new {method_name}IxCols({table_name_lit}));" - ); - } - }); - writeln!(output); + self.from(&mut output, module, options); writeln!(output, "public sealed class TypedSubscriptionBuilder"); indented_block(&mut output, |output| { @@ -1160,7 +1429,12 @@ impl Lang for Csharp<'_> { writeln!(output, "public abstract partial class Reducer"); indented_block(&mut output, |output| { // Prevent instantiation of this class from outside. - writeln!(output, "private Reducer() {{ }}"); + let visibility = if module.submodules().is_empty() { + "private" + } else { + "private protected" + }; + writeln!(output, "{visibility} Reducer() {{ }}"); }); writeln!(output); @@ -1241,6 +1515,16 @@ impl Lang for Csharp<'_> { "Reducer.{reducer_name} args => Reducers.Invoke{reducer_name}(eventContext, args)," ); } + for (path, _, reducer) in module + .all_reducers_with_prefix() + .into_iter() + .filter(|(path, _, reducer)| !path.is_empty() && !reducer.visibility.is_private()) + { + let namespace = clr_namespace(self.root_namespace, &path); + let member = member_path(&path); + let name = reducer.accessor_name.deref().to_case(Case::Pascal); + writeln!(output, "global::{namespace}.Reducer.{name} args => Reducers.{member}Invoke{name}(eventContext, args),"); + } writeln!( output, r#"_ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {{reducer}}")"# diff --git a/crates/codegen/tests/codegen.rs b/crates/codegen/tests/codegen.rs index 8116c0291fc..1207809589a 100644 --- a/crates/codegen/tests/codegen.rs +++ b/crates/codegen/tests/codegen.rs @@ -10,6 +10,11 @@ fn compiled_module() -> &'static ModuleDef { .get_or_init(|| CompiledModule::compile("module-test", CompilationMode::Debug).extract_schema_blocking()) } +fn compiled_typescript_module() -> &'static ModuleDef { + static MODULE: OnceLock = OnceLock::new(); + MODULE.get_or_init(|| CompiledModule::compile("module-test-ts", CompilationMode::Debug).extract_schema_blocking()) +} + macro_rules! declare_tests { ($($name:ident => $lang:expr,)*) => ($( #[test] @@ -70,8 +75,8 @@ fn test_typescript_table_handles_are_camel_case() { /// submodule, so this checks the TypeScript output of one that does. #[test] fn submodule_names_use_canonical_wire_names_and_accessor_paths() { - let module = CompiledModule::compile("module-test-ts", CompilationMode::Debug).extract_schema_blocking(); - let files = generate(&module, &TypeScript, &CodegenOptions::default()); + let module = compiled_typescript_module(); + let files = generate(module, &TypeScript, &CodegenOptions::default()); let filenames: Vec<_> = files.iter().map(|f| f.filename.clone()).collect(); let code = files.into_iter().map(|f| f.code).collect::>().join("\n"); @@ -123,3 +128,214 @@ fn submodule_names_use_canonical_wire_names_and_accessor_paths() { "generated files must live under the accessor namespace directory; got {filenames:?}" ); } + +fn namespace_module() -> ModuleDef { + use spacetimedb_lib::db::raw_def::v10::{ + RawModuleDefV10, RawModuleDefV10Builder, RawModuleDefV10Section, RawSubmoduleV10, + }; + use spacetimedb_lib::db::raw_def::v9::TableAccess; + use spacetimedb_lib::sats::{AlgebraicType, ProductType}; + + fn scope(value_type: AlgebraicType) -> RawModuleDefV10 { + let mut builder = RawModuleDefV10Builder::new(); + let row = builder + .build_table_with_new_type( + "User", + ProductType::from([("id", AlgebraicType::U64), ("value", value_type)]), + true, + ) + .with_primary_key(0) + .with_unique_constraint(spacetimedb_primitives::ColId(0)) + .with_index( + spacetimedb_lib::db::raw_def::v9::btree(spacetimedb_primitives::ColId(0)), + "user_id", + "Id", + ) + .finish(); + builder + .build_table_with_new_type("Secret", ProductType::from([("id", AlgebraicType::U64)]), true) + .with_access(TableAccess::Private) + .finish(); + builder + .build_table_with_new_type("Notice", ProductType::from([("id", AlgebraicType::U64)]), true) + .with_event(true) + .finish(); + builder.add_reducer("Login", ProductType::from([("user", AlgebraicType::Ref(row))])); + builder.add_procedure( + "GetUser", + ProductType::from([] as [(&str, AlgebraicType); 0]), + AlgebraicType::Ref(row), + ); + builder.add_view( + "Users", + 0, + true, + true, + ProductType::from([] as [(&str, AlgebraicType); 0]), + AlgebraicType::array(AlgebraicType::Ref(row)), + ); + let payload = builder.add_algebraic_type( + [], + "Payload", + AlgebraicType::Product(ProductType::from([("value", AlgebraicType::String)])), + true, + ); + builder.add_procedure( + "GetPayload", + ProductType::from([] as [(&str, AlgebraicType); 0]), + AlgebraicType::Ref(payload), + ); + builder.finish() + } + + let mut root = scope(AlgebraicType::Bool); + let mut auth = scope(AlgebraicType::U32); + auth.sections + .push(RawModuleDefV10Section::Submodules(vec![RawSubmoduleV10 { + namespace: "nested".into(), + module: scope(AlgebraicType::I64), + }])); + root.sections.push(RawModuleDefV10Section::Submodules(vec![ + RawSubmoduleV10 { + namespace: "MyAuth".into(), + module: auth, + }, + RawSubmoduleV10 { + namespace: "class".into(), + module: scope(AlgebraicType::String), + }, + RawSubmoduleV10 { + namespace: "Empty".into(), + module: RawModuleDefV10::default(), + }, + ])); + root.try_into().expect("namespace fixture should validate") +} + +#[test] +fn csharp_namespaces_compile_and_run() { + let module = namespace_module(); + let files = generate( + &module, + &Csharp { + namespace: "Game.Bindings", + }, + &CodegenOptions::default(), + ); + let unique_names: std::collections::HashSet<_> = files.iter().map(|file| &file.filename).collect(); + assert_eq!(unique_names.len(), files.len(), "generated filenames must be unique"); + assert!(!files.iter().any(|file| file.filename.ends_with("Tables/Secret.g.cs"))); + let auth_reducer = files + .iter() + .find(|file| file.filename == "MyAuth/Reducers/Login.g.cs") + .unwrap(); + assert!(auth_reducer.code.contains("\"MyAuth.login\"")); + assert!(!auth_reducer.code.contains("MyAuth.MyAuth.")); + + compile_csharp_client(files, include_str!("csharp-namespaces/Program.cs")); +} + +#[test] +fn csharp_client_for_typescript_submodule_compiles_and_runs() { + let typescript = compiled_typescript_module(); + compile_csharp_client( + generate( + typescript, + &Csharp { + namespace: "SpacetimeDB", + }, + &CodegenOptions::default(), + ), + r#"class Program { static void Main() { + var conn = new SpacetimeDB.DbConnection(); + try { + if (conn.Db.lib.LibData.RemoteTableName != "lib.libData") throw new System.Exception(conn.Db.lib.LibData.RemoteTableName); + if (((SpacetimeDB.IReducerArgs)new SpacetimeDB.lib.Reducer.LibInsert("value")).ReducerName != "lib.lib_insert") throw new System.Exception("wrong reducer name"); + } finally { conn.Disconnect(); } + } }"#, + ); +} + +fn compile_csharp_client(files: Vec, program: &str) { + // Project references share the SDK's MSBuild intermediate directory. + static COMPILE: std::sync::Mutex<()> = std::sync::Mutex::new(()); + let _guard = COMPILE.lock().unwrap_or_else(|poison| poison.into_inner()); + let project = tempfile::tempdir().unwrap(); + for file in files { + let path = project.path().join(file.filename); + fs_err::create_dir_all(path.parent().unwrap()).unwrap(); + fs_err::write(path, file.code).unwrap(); + } + let repo = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../..") + .canonicalize() + .unwrap(); + // Use the local runtime, never a published package or an old NuGet cache entry. + let config = project.path().join("NuGet.Config"); + fs_err::write( + &config, + format!( + r#" + + + + + + + + + +"#, + repo.display() + ), + ) + .unwrap(); + static PACKED: OnceLock<()> = OnceLock::new(); + PACKED.get_or_init(|| { + let result = std::process::Command::new("dotnet") + .arg("pack") + .arg(repo.join("crates/bindings-csharp/BSATN.Runtime")) + .args(["-c", "Release"]) + .arg(format!("-p:RestoreConfigFile={}", config.display())) + .output() + .expect("dotnet SDK is required for generated C# compilation"); + assert!( + result.status.success(), + "local BSATN pack failed:\n{}\n{}", + String::from_utf8_lossy(&result.stdout), + String::from_utf8_lossy(&result.stderr) + ); + }); + fs_err::write(project.path().join("Program.cs"), program).unwrap(); + fs_err::write( + project.path().join("client.csproj"), + format!( + r#" + + net8.0 + 9 + Exe + enable + SpacetimeDB.Tests + + +"#, + repo.display() + ), + ) + .unwrap(); + let result = std::process::Command::new("dotnet") + .args(["run", "--project"]) + .arg(project.path().join("client.csproj")) + .arg("-p:TreatWarningsAsErrors=true") + .arg(format!("-p:RestorePackagesPath={}/packages", project.path().display())) + .arg(format!("-p:RestoreConfigFile={}", config.display())) + .output() + .expect("dotnet SDK is required for generated C# compilation"); + assert!( + result.status.success(), + "generated client failed:\n{}\n{}", + String::from_utf8_lossy(&result.stdout), + String::from_utf8_lossy(&result.stderr) + ); +} diff --git a/crates/codegen/tests/csharp-namespaces/Program.cs b/crates/codegen/tests/csharp-namespaces/Program.cs new file mode 100644 index 00000000000..8629ed8bca6 --- /dev/null +++ b/crates/codegen/tests/csharp-namespaces/Program.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Game.Bindings; +using SpacetimeDB; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using Auth = Game.Bindings.MyAuth; +using Audit = Game.Bindings.@class; +using Nested = Game.Bindings.MyAuth.nested; + +internal static class Program +{ + private static void Equal(T expected, T actual) + { + if (!EqualityComparer.Default.Equals(expected, actual)) + throw new Exception($"Expected {expected}, got {actual}"); + } + + private static BsatnRowList Rows(params IStructuralReadWrite[] rows) + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + var offsets = new List(); + foreach (var row in rows) + { + offsets.Add((ulong)stream.Length); + row.WriteFields(writer); + } + return new BsatnRowList(new RowSizeHint.RowOffsets(offsets), stream.ToArray().ToList()); + } + + private static TableUpdate Change(string name, IStructuralReadWrite[] inserts, IStructuralReadWrite[] deletes) => + new TableUpdate(name, new List + { + new TableUpdateRows.PersistentTable(new PersistentTableRows(Rows(inserts), Rows(deletes))) + }); + + private static void Apply(DbConnection conn, params TableUpdate[] updates) + { + var parsed = ParsedDatabaseUpdate.New(); + foreach (var update in updates) + conn.Db.GetTable(update.TableName)!.Parse(update, parsed); + var ctx = new EventContext(conn, new Event.UnknownTransaction()); + foreach (var (table, delta) in parsed.Updates) table.PreApply(ctx, delta); + foreach (var (table, delta) in parsed.Updates) table.Apply(ctx, delta); + foreach (var (table, _) in parsed.Updates) table.PostApply(ctx); + } + + private static void Main() + { + var conn = new DbConnection(); + try + { + Check(conn); + } + finally + { + conn.Disconnect(); + } + } + + private static void Check(DbConnection conn) + { + Equal("user", conn.Db.User.RemoteTableName); + Equal("MyAuth.user", conn.Db.MyAuth.User.RemoteTableName); + Equal("class.user", conn.Db.@class.User.RemoteTableName); + Equal("MyAuth.nested.user", conn.Db.MyAuth.nested.User.RemoteTableName); + Equal(conn.Db.MyAuth.User, conn.Db.GetTable("MyAuth.user")!); + Equal(conn.Db.@class.User, conn.Db.GetTable("class.user")!); + Equal(conn.Db.MyAuth.nested.User, conn.Db.GetTable("MyAuth.nested.user")!); + + var query = new QueryBuilder(); + Equal("SELECT * FROM \"user\"", query.From.User().ToSql()); + Equal("SELECT * FROM \"MyAuth\".\"user\"", query.From.MyAuth.User().ToSql()); + Equal("SELECT * FROM \"class\".\"user\"", query.From.@class.User().ToSql()); + Equal("SELECT * FROM \"MyAuth\".\"nested\".\"user\"", query.From.MyAuth.nested.User().ToSql()); + var filtered = query.From.MyAuth.User().Where(cols => cols.Value.Eq(7U)).ToSql(); + if (!filtered.Contains("\"MyAuth\".\"user\".\"value\"")) throw new Exception(filtered); + var join = " FROM \"MyAuth\".\"user\" JOIN \"class\".\"user\" ON \"MyAuth\".\"user\".\"id\" = \"class\".\"user\".\"id\""; + Equal("SELECT \"MyAuth\".\"user\".*" + join, query.From.MyAuth.User().LeftSemijoin(query.From.@class.User(), (l, r) => l.Id.Eq(r.Id)).ToSql()); + Equal("SELECT \"class\".\"user\".*" + join, query.From.MyAuth.User().RightSemijoin(query.From.@class.User(), (l, r) => l.Id.Eq(r.Id)).ToSql()); + var all = QueryBuilder.AllTablesSqlQueries(); + Equal(12, all.Length); + Equal(all.Length, all.Distinct().Count()); + Equal(false, all.Any(sql => sql.Contains("secret"))); + var sqlName = typeof(Auth.RemoteTables.UserHandle).GetProperty("RemoteSqlTableName", BindingFlags.Instance | BindingFlags.NonPublic)!; + Equal("\"MyAuth\".\"user\"", sqlName.GetValue(conn.Db.MyAuth.User)!.ToString()); + + var root = new User(1, true); + var auth = new Auth.User(1, 7); + var audit = new Audit.User(1, "audit"); + var nested = new Nested.User(1, -1); + int inserts = 0; + conn.Db.MyAuth.User.OnInsert += (ctx, row) => + { + Equal(conn.Db, ctx.Db); + Equal(1, ctx.Db.User.Count); + Equal(1, ctx.Db.@class.User.Count); + Equal(7U, row.Value); + inserts++; + }; + Apply(conn, + Change("user", new[] { root }, Array.Empty()), + Change("MyAuth.user", new[] { auth }, Array.Empty()), + Change("class.user", new[] { audit }, Array.Empty()), + Change("MyAuth.nested.user", new[] { nested }, Array.Empty())); + Equal(1, inserts); + Equal(auth, conn.Db.MyAuth.User.Id.Find(1)); + Equal(audit, conn.Db.@class.User.Id.Find(1)); + Equal("audit", conn.Db.@class.User.Iter().Single().Value); + Equal(-1L, conn.Db.MyAuth.nested.User.Iter().Single().Value); + int updates = 0; + conn.Db.MyAuth.User.OnUpdate += (ctx, oldRow, newRow) => + { + Equal(7U, oldRow.Value); + Equal(8U, newRow.Value); + Equal("audit", ctx.Db.@class.User.Id.Find(1)!.Value); + updates++; + }; + var updatedAuth = new Auth.User(1, 8); + Apply(conn, Change("MyAuth.user", new[] { updatedAuth }, new[] { auth })); + Equal(1, updates); + auth = updatedAuth; + Apply(conn, Change("MyAuth.user", Array.Empty(), new[] { auth })); + Equal(0, conn.Db.MyAuth.User.Count); + Equal(1, conn.Db.User.Count); + Equal(1, conn.Db.@class.User.Count); + + int notices = 0; + conn.Db.MyAuth.Notice.OnInsert += (ctx, row) => { Equal(4UL, row.Id); notices++; }; + Apply(conn, new TableUpdate("MyAuth.notice", new List + { + new TableUpdateRows.EventTable(new EventTableRows(Rows(new Auth.Notice(4)))) + })); + Equal(1, notices); + + Equal("MyAuth.login", ((IReducerArgs)new Auth.Reducer.Login(auth)).ReducerName); + Equal("class.login", ((IReducerArgs)new Audit.Reducer.Login(audit)).ReducerName); + Equal("MyAuth.nested.get_user", ((IProcedureArgs)new Nested.Procedure.GetUserArgs()).ProcedureName); + // Function-only types are emitted and remain in their owning typespace. + _ = new Auth.Procedure.GetPayload { Value = new Auth.Payload("auth") }; + _ = new Audit.Procedure.GetUser { Value = audit }; + _ = new Auth.Procedure.GetUser { Value = auth }; + + int authCalls = 0, auditCalls = 0, errors = 0; + conn.Reducers.MyAuth.OnLogin += (ctx, row) => { Equal(auth, row); authCalls++; }; + conn.Reducers.@class.OnLogin += (ctx, row) => { Equal(audit, row); auditCalls++; }; + conn.OnUnhandledReducerError += (ctx, error) => { Equal("failed", error.Message); errors++; }; + var dispatch = typeof(DbConnection).GetMethod("Dispatch", BindingFlags.NonPublic | BindingFlags.Instance)!; + void Dispatch(Reducer args, Status status) + { + var ev = new ReducerEvent(new Timestamp(0), status, Identity.From(new byte[32]), null, null, args); + dispatch.Invoke(conn, new object[] { new ReducerEventContext(conn, ev), args }); + } + Dispatch(new Auth.Reducer.Login(auth), new Status.Committed(new Unit())); + Dispatch(new Audit.Reducer.Login(audit), new Status.Committed(new Unit())); + Dispatch(new Nested.Reducer.Login(nested), new Status.Failed("failed")); + Equal(1, authCalls); + Equal(1, auditCalls); + Equal(1, errors); + Console.WriteLine("Namespace client checks passed."); + } +} diff --git a/sdks/csharp/DEVELOP.md b/sdks/csharp/DEVELOP.md index 2ffd13c1476..ba1f78c529d 100644 --- a/sdks/csharp/DEVELOP.md +++ b/sdks/csharp/DEVELOP.md @@ -48,6 +48,21 @@ When SDK code needs to refer to generated types, we have two options: The most important generated types are `RemoteTables` -- also known as the **client cache** -- and `RemoteReducers`. `RemoteTables` stores the local view of subscribed data from the database. For a `DbConnection conn`, `conn.Db` is an instance of `RemoteTables`. `RemoteReducers` allows calling reducers on the server, and is accessible at `conn.Reducers`. Types are also generated for all server-side types referred to by tables or modules. +### Namespace bindings + +Suppose a dependency is mounted in the database namespace `MyAuth`, using +`Accessor = "MyAuth"`. Generated C# clients expose its tables through +`conn.Db.MyAuth`, reducers through `conn.Reducers.MyAuth`, procedures through +`conn.Procedures.MyAuth`, and query factories through `q.From.MyAuth`. +The mount accessor is also the database namespace; its spelling is preserved. + +The `--namespace` option of `spacetime generate` controls where generated C# +classes are declared; it does not name or rename database namespaces. With +`--namespace Game.Bindings`, a root `User` row becomes `Game.Bindings.User`, +while a `User` row in the `MyAuth` database namespace becomes +`Game.Bindings.MyAuth.User`. Their table handles remain `conn.Db.User` and +`conn.Db.MyAuth.User`, respectively. + ### Runtime Structure Most of the core logic of the SDK lives in [`DbConnectionBase<...>`](./src/SpacetimeDBClient.cs). This handles: @@ -99,4 +114,3 @@ We could deduplicate multiply-subscribed rows server-side, but this represents a There is also a class `MultiDictionaryDelta`. This represents a pre-processed batch of changes to a `MultiDictionary`. We prepare `MultiDictionaryDelta`s on a background thread and `Apply` them on the main thread. This allows us to do at least some work without blocking the main thread. Note that if multiple subscriptions are subscribed to a row, when a server-side transaction updates that row, exactly the right number of updates will be sent over the network, in a single `ServerMessage`. `MultiDictionary` and `MultiDictionaryDelta` rely on this guarantee for correct operation, and will throw exceptions in debug mode if it is not met. - diff --git a/sdks/csharp/src/Table.cs b/sdks/csharp/src/Table.cs index 680dfc11b52..f841112374b 100644 --- a/sdks/csharp/src/Table.cs +++ b/sdks/csharp/src/Table.cs @@ -176,6 +176,9 @@ internal class ParsedTableUpdate : IParsedTableUpdate public abstract string RemoteTableName { get; } string IRemoteTableHandle.RemoteTableName => RemoteTableName; + /// The SQL identifier, separate from the wire/cache key. + protected virtual SqlTableName RemoteSqlTableName => new(RemoteTableName); + /// /// Whether this table is an event table. /// Event tables don't persist rows in the client cache — they only fire insert callbacks. @@ -417,7 +420,7 @@ public event RowEventHandler OnInsert public IEnumerable Iter() => Entries.Values; public Task RemoteQuery(string query) => - conn.RemoteQuery($"SELECT {RemoteTableName}.* FROM {RemoteTableName} {query}"); + conn.RemoteQuery($"SELECT {RemoteSqlTableName}.* FROM {RemoteSqlTableName} {query}"); void InvokeInsert(IEventContext context, IStructuralReadWrite row) { From e3d0412428891699f5d364aa484940a5c00bfa64 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 17 Sep 2026 15:03:35 -0500 Subject: [PATCH 11/49] Add integration tests --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 4 +- crates/bindings-csharp/Codegen/Diag.cs | 2 +- crates/bindings-csharp/Codegen/Module.cs | 6 +- .../libraries/AuthLib/Lib.cs | 41 +- .../regression-tests/namespaces/Program.cs | 350 +++++++++ .../regression-tests/namespaces/README.md | 40 + .../regression-tests/namespaces/client.csproj | 13 + .../module_bindings/MyAuth/Namespace.g.cs | 50 ++ .../MyAuth/Procedures/CountUsers.g.cs | 64 ++ .../MyAuth/Procedures/ReadScore.g.cs | 76 ++ .../module_bindings/MyAuth/Reducers/Add.g.cs | 66 ++ .../module_bindings/MyAuth/Reducers/Fail.g.cs | 66 ++ .../MyAuth/Reducers/Remove.g.cs | 66 ++ .../MyAuth/Reducers/Update.g.cs | 73 ++ .../MyAuth/Tables/AnonymousUsers.g.cs | 48 ++ .../module_bindings/MyAuth/Tables/Notice.g.cs | 46 ++ .../MyAuth/Tables/QueryUsers.g.cs | 62 ++ .../module_bindings/MyAuth/Tables/User.g.cs | 74 ++ .../module_bindings/MyAuth/Tables/Users.g.cs | 48 ++ .../module_bindings/MyAuth/Types/Notice.g.cs | 28 + .../module_bindings/MyAuth/Types/Secret.g.cs | 28 + .../module_bindings/MyAuth/Types/User.g.cs | 34 + .../Procedures/CountUsers.g.cs | 64 ++ .../module_bindings/Reducers/Exercise.g.cs | 53 ++ .../module_bindings/Reducers/Extra.g.cs | 53 ++ .../module_bindings/SpacetimeDBClient.g.cs | 681 ++++++++++++++++++ .../module_bindings/Tables/AuthUsers.g.cs | 45 ++ .../module_bindings/Tables/ExtraRow.g.cs | 59 ++ .../module_bindings/Tables/ExtraRows.g.cs | 45 ++ .../module_bindings/Tables/QueryExtra.g.cs | 59 ++ .../module_bindings/Tables/QueryUsers.g.cs | 59 ++ .../Tables/QueryUsersRight.g.cs | 59 ++ .../module_bindings/Tables/User.g.cs | 59 ++ .../module_bindings/Tables/Users.g.cs | 45 ++ .../module_bindings/Types/AuthSummary.g.cs | 28 + .../module_bindings/Types/ExtraRow.g.cs | 28 + .../module_bindings/Types/User.g.cs | 28 + .../module_bindings/class/Namespace.g.cs | 42 ++ .../class/Procedures/CountUsers.g.cs | 64 ++ .../module_bindings/class/Reducers/Add.g.cs | 66 ++ .../module_bindings/class/Tables/User.g.cs | 62 ++ .../module_bindings/class/Types/User.g.cs | 35 + sdks/csharp/tools~/gen-regression-tests.sh | 4 + sdks/csharp/tools~/run-regression-tests.sh | 6 + 44 files changed, 2922 insertions(+), 7 deletions(-) create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/Program.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/README.md create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/client.csproj create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/CountUsers.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadScore.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Add.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Fail.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Remove.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Update.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/Notice.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/Secret.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/User.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/CountUsers.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/Exercise.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/Extra.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/AuthUsers.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/ExtraRow.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/ExtraRows.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/QueryExtra.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/QueryUsers.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/QueryUsersRight.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/User.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/Users.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Types/AuthSummary.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Types/ExtraRow.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Types/User.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Namespace.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Procedures/CountUsers.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Reducers/Add.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/User.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/User.g.cs diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 9e690cfa4eb..248b0449e31 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -743,7 +743,7 @@ public static bool CheckNamespaces() if (registry.Resolve(first, "User") != "auth_data.User" || registry.Resolve(second, "User") != "audit_data.User" || registry.Resolve("root", "User") != "User" - || registry.Resolve("unmounted", "User") != "User" + || registry.Resolve("publicDependency", "User") != "User" || registry.Resolve("merged", "User") != "User") return false; try { SpacetimeDB.Internal.Module.ResolveName(first, "User"); return false; } @@ -751,7 +751,7 @@ public static bool CheckNamespaces() SpacetimeDB.Internal.Module.InstallNamespaces(registry); if (SpacetimeDB.Internal.Module.ResolveName(first, "User") != "auth_data.User") return false; if (SpacetimeDB.Internal.Module.ResolveSqlName(first, "User").ToString() != "\"auth_data\".\"User\"") return false; - if (registry.ResolveSqlName("unmounted", "User").ToString() != "\"User\"") return false; + if (registry.ResolveSqlName("publicDependency", "User").ToString() != "\"User\"") return false; if (registry.ResolveSqlName("merged", "User").ToString() != "\"User\"") return false; if (registry.ResolveSqlName("root", "User.With.Dot").ToString() != "\"User.With.Dot\"") return false; try { SpacetimeDB.Internal.Module.InstallNamespaces(registry); return false; } diff --git a/crates/bindings-csharp/Codegen/Diag.cs b/crates/bindings-csharp/Codegen/Diag.cs index a81b02475f6..d98bfc99e35 100644 --- a/crates/bindings-csharp/Codegen/Diag.cs +++ b/crates/bindings-csharp/Codegen/Diag.cs @@ -389,7 +389,7 @@ string type new( group, "Mounted dependency declares lifecycle reducers", - ctx => $"Dependency '{ctx.assembly}' mounted in namespace '{ctx.name}' declares lifecycle reducers: {ctx.reducers}. Lifecycle reducers are only supported in the root scope; remove them or leave the dependency unmounted.", + ctx => $"Dependency '{ctx.assembly}' mounted in namespace '{ctx.name}' declares lifecycle reducers: {ctx.reducers}. Lifecycle reducers are only supported in the root scope; remove them or omit the dependency's namespace declaration so it registers automatically in public.", _ => Location.None ); } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 42a3ccf9af7..c38361c60c3 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -2617,9 +2617,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context) bool IsChild(AssemblyDeclaration assembly) => mountByIdentity.TryGetValue(assembly.Identity, out var mount) && !mount.Accessor.Equals("public", StringComparison.OrdinalIgnoreCase); - var unmountedAssemblies = assemblies.Where(a => !IsChild(a)).ToArray(); + var publicScopeAssemblies = assemblies.Where(a => !IsChild(a)).ToArray(); var mountedAssemblies = assemblies.Where(IsChild).ToArray(); - var registrationOrder = unmountedAssemblies.Concat(mountedAssemblies).ToArray(); + var registrationOrder = publicScopeAssemblies.Concat(mountedAssemblies).ToArray(); foreach (var assembly in assemblies.Where(a => a.DeclaresMounts)) context.ReportDiagnostic(ErrorDescriptor.DependencyNamespaceMounts.ToDiag(assembly.Identity)); foreach (var assembly in mountedAssemblies.Where(a => a.LifecycleReducers.Length != 0)) @@ -2707,7 +2707,7 @@ void Add(string name, string owner, string declaration) $"new({SymbolDisplay.FormatLiteral(m.AssemblyIdentity, true)}, {SymbolDisplay.FormatLiteral(m.Accessor, true)})")) + "}));", $"global::{extensionNamespaceName}.AssemblyDescriptor.Register(global::SpacetimeDB.Internal.Module.RootBuilder);" }; - foreach (var assembly in unmountedAssemblies) + foreach (var assembly in publicScopeAssemblies) compositionRegistration.Add($"{assembly.DescriptorTypeName}.Register(global::SpacetimeDB.Internal.Module.RootBuilder);"); for (var i = 0; i < mountedAssemblies.Length; i++) { diff --git a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs index dc325496899..79e7c37db18 100644 --- a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs +++ b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs @@ -15,6 +15,18 @@ public partial struct User public uint Score; } +[Table(Accessor = "Notice", Public = true, Event = true)] +public partial struct Notice +{ + public uint Id; +} + +[Table(Accessor = "Secret")] +public partial struct Secret +{ + public uint Id; +} + public static partial class Functions { public static void Insert(ReducerContext ctx, uint id) => @@ -29,7 +41,34 @@ public static FromWhere Query(ViewContext ctx) => public static IQuery QueryUsers(ViewContext ctx) => Query(ctx); [Reducer] - public static void Add(ReducerContext ctx, uint id) => Insert(ctx, id); + public static void Add(ReducerContext ctx, uint id) + { + Insert(ctx, id); + ctx.Db.Notice.Insert(new Notice { Id = id }); + ctx.Db.Secret.Insert(new Secret { Id = id }); + } + + [Reducer] + public static void Fail(ReducerContext ctx, uint id) + { + Insert(ctx, id); + throw new Exception("namespace rollback"); + } + + [Reducer] + public static void Update(ReducerContext ctx, uint id, uint score) + { + var row = ctx.Db.User.Id.Find(id)!.Value; + row.Score = score; + ctx.Db.User.Id.Update(row); + } + + [Reducer] + public static void Remove(ReducerContext ctx, uint id) => ctx.Db.User.Id.Delete(id); + + [Procedure] + public static uint ReadScore(ProcedureContext ctx, uint id) => + ctx.WithTx(tx => tx.Db.User.Id.Find(id)?.Score ?? throw new Exception("missing auth user")); [Procedure] public static ulong CountUsers(ProcedureContext ctx) => ctx.WithTx(tx => tx.Db.User.Count); diff --git a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs new file mode 100644 index 00000000000..124748d95ee --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs @@ -0,0 +1,350 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using SpacetimeDB; +using SpacetimeDB.Types; + +internal static class Program +{ + private static void Require(bool condition, string message) + { + if (!condition) + throw new Exception(message); + } + + private static void Main() + { + var host = + Environment.GetEnvironmentVariable("SPACETIMEDB_SERVER_URL") ?? "http://localhost:3000"; + if (host == "local") + host = "http://localhost:3000"; + var connected = false; + Exception? connectionError = null; + var conn = DbConnection + .Builder() + .WithUri(host) + .WithDatabaseName("namespace-tests") + .OnConnect((_, _, _) => connected = true) + .OnConnectError(error => connectionError = error) + .OnDisconnect( + (_, error) => connectionError = error ?? new Exception("Unexpected disconnect") + ) + .Build(); + + void Wait(Func done, string phase) + { + var timer = Stopwatch.StartNew(); + while (!done()) + { + if (connectionError != null) + throw connectionError; + if (timer.Elapsed > TimeSpan.FromSeconds(30)) + throw new TimeoutException(phase); + conn.FrameTick(); + Thread.Sleep(5); + } + if (connectionError != null) + throw connectionError; + } + + void Unsubscribe(SubscriptionHandle handle) + { + var done = false; + handle.UnsubscribeThen(_ => done = true); + Wait(() => done, "unsubscribe"); + } + + void EmptyCache() + { + Require( + conn.Db.User.Count == 0 + && conn.Db.MyAuth.User.Count == 0 + && conn.Db.@class.User.Count == 0 + && conn.Db.ExtraRow.Count == 0, + "Unsubscribe must clear every namespace's table cache" + ); + Require( + conn.Db.Users.Count == 0 + && conn.Db.MyAuth.Users.Count == 0 + && conn.Db.MyAuth.QueryUsers.Count == 0 + && conn.Db.MyAuth.AnonymousUsers.Count == 0 + && conn.Db.AuthUsers.Count == 0 + && conn.Db.QueryUsers.Count == 0 + && conn.Db.QueryUsersRight.Count == 0 + && conn.Db.QueryExtra.Count == 0, + "Unsubscribe must clear view caches" + ); + } + + try + { + Wait(() => connected, "connect"); + Require( + conn.Db.MyAuth.User.RemoteTableName == "MyAuth.auth_users", + "Explicit table wire name" + ); + Require( + conn.Db.@class.User.RemoteTableName == "class.user", + "Keyword namespace wire name" + ); + Require( + !QueryBuilder.AllTablesSqlQueries().Any(sql => sql.Contains("secret")), + "Subscribe-all must omit private child tables" + ); + + var applied = false; + var subscription = conn.SubscriptionBuilder() + .OnApplied(_ => applied = true) + .OnError((_, error) => throw error) + .AddQuery(q => q.From.User()) + .AddQuery(q => q.From.MyAuth.User()) + .AddQuery(q => q.From.@class.User()) + .AddQuery(q => q.From.ExtraRow()) + .AddQuery(q => q.From.Users()) + .AddQuery(q => q.From.MyAuth.Users()) + .AddQuery(q => q.From.MyAuth.AnonymousUsers()) + .AddQuery(q => q.From.MyAuth.QueryUsers()) + .AddQuery(q => q.From.MyAuth.Notice()) + .Subscribe(); + Wait(() => applied, "typed subscription"); + EmptyCache(); + + conn.Reducers.Extra(); + Wait(() => conn.Db.ExtraRow.Count == 1, "dependency automatically registered in public"); + var exerciseDone = false; + var atomicInsert = false; + conn.Db.User.OnInsert += (ctx, row) => + { + if (row.Id != 2) + return; + Require( + ctx.Db.MyAuth.User.Id.Find(2)?.Score == 99 + && ctx.Db.@class.User.Id.Find(4)?.Message == "consumer", + "Root callback must see the complete cross-namespace transaction" + ); + atomicInsert = true; + }; + conn.Reducers.OnExercise += (ctx) => + { + Require(ctx.Event.Status is Status.Committed, "Exercise failed"); + exerciseDone = true; + }; + conn.Reducers.Exercise(); + Wait( + () => + exerciseDone + && atomicInsert + && conn.Db.MyAuth.Users.Count == 1 + && conn.Db.MyAuth.AnonymousUsers.Count == 1 + && conn.Db.MyAuth.QueryUsers.Count == 1, + "cross-library helper writes and views" + ); + Require( + conn.Db.User.Count == 1 + && conn.Db.MyAuth.User.Count == 1 + && conn.Db.@class.User.Count == 1, + "Same-named table caches must be independent" + ); + + var joinApplied = false; + var joins = conn.SubscriptionBuilder() + .OnApplied(_ => joinApplied = true) + .OnError((_, error) => throw error) + .AddQuery(q => + q.From.User().LeftSemijoin(q.From.MyAuth.User(), (r, a) => r.Id.Eq(a.Id)) + ) + .AddQuery(q => + q.From.User().RightSemijoin(q.From.MyAuth.User(), (r, a) => r.Id.Eq(a.Id)) + ) + .AddQuery(q => q.From.MyAuth.User().Where(c => c.Score.Eq(99u))) + .Subscribe(); + Wait(() => joinApplied, "cross-namespace semijoins and filter"); + Require( + conn.Db.User.Count == 1 && conn.Db.MyAuth.User.Count == 1, + "Overlapping queries duplicate rows" + ); + Unsubscribe(joins); + Require( + conn.Db.User.Count == 1 && conn.Db.MyAuth.User.Count == 1, + "Overlapping unsubscribe removed live rows" + ); + + var authAdded = false; + var auditAdded = false; + var notices = 0; + conn.Db.MyAuth.Notice.OnInsert += (_, row) => + { + Require(row.Id == 10, "Event routed to wrong namespace"); + notices++; + }; + conn.Reducers.MyAuth.OnAdd += (ctx, id) => + { + Require(ctx.Event.Status is Status.Committed && id == 10, "Auth reducer result"); + Require(ctx.Db.MyAuth.User.Id.Find(id)?.Score == 42, "Auth reducer callback cache"); + authAdded = true; + }; + conn.Reducers.@class.OnAdd += (ctx, id) => + { + Require(ctx.Event.Status is Status.Committed && id == 10, "Audit reducer result"); + Require( + ctx.Db.@class.User.Id.Find(id)?.Message == "audit", + "Audit reducer callback cache" + ); + auditAdded = true; + }; + conn.Reducers.MyAuth.Add(10); + conn.Reducers.@class.Add(10); + Wait( + () => authAdded && auditAdded && notices == 1, + "same-named reducers and event table" + ); + Require( + conn.Db.User.Count == 1 + && conn.Db.MyAuth.User.Count == 2 + && conn.Db.@class.User.Count == 2, + "Namespaced reducers changed the wrong table" + ); + + var procedures = 0; + conn.Procedures.CountUsers( + (_, result) => + { + Require(result.IsSuccess && result.Value == 5, "Root procedure"); + procedures++; + } + ); + conn.Procedures.MyAuth.CountUsers( + (_, result) => + { + Require(result.IsSuccess && result.Value == 2, "Auth procedure"); + procedures++; + } + ); + conn.Procedures.@class.CountUsers( + (_, result) => + { + Require(result.IsSuccess && result.Value == 2, "Audit procedure"); + procedures++; + } + ); + conn.Procedures.MyAuth.ReadScore( + 10, + (_, result) => + { + Require(result.IsSuccess && result.Value == 42, "Procedure return value"); + procedures++; + } + ); + conn.Procedures.MyAuth.ReadScore( + 999, + (_, result) => + { + Require( + !result.IsSuccess && result.Error != null, + "Procedure failure callback" + ); + procedures++; + } + ); + Wait(() => procedures == 5, "namespaced procedure callbacks"); + + var updated = false; + conn.Db.MyAuth.User.OnUpdate += (ctx, before, after) => + { + Require( + before.Id == 10 && before.Score == 42 && after.Score == 77, + "Update callback values" + ); + Require( + ctx.Db.MyAuth.User.ByScore.Filter(77u).Single().Id == 10, + "Updated index cache" + ); + updated = true; + }; + conn.Reducers.MyAuth.Update(10, 77); + Wait(() => updated, "namespaced update"); + var remote = conn.Db.MyAuth.User.RemoteQuery("WHERE id = 10"); + Wait(() => remote.IsCompleted, "namespaced RemoteQuery"); + Require( + remote.GetAwaiter().GetResult().Single().Score == 77, + "RemoteQuery result decoding" + ); + var privateDenied = false; + conn.SubscriptionBuilder() + .OnApplied(_ => throw new Exception("A non-owner subscribed to private child data")) + .OnError((_, _) => privateDenied = true) + .Subscribe(new[] { "SELECT * FROM \"MyAuth\".secret" }); + Wait(() => privateDenied, "private child subscription rejection"); + + var failed = false; + conn.OnUnhandledReducerError += (_, error) => + { + Require(error.Message.Contains("namespace rollback"), "Unexpected reducer failure"); + failed = true; + }; + conn.Reducers.MyAuth.Fail(999); + Wait(() => failed, "child error forwarded to root"); + var rolledBack = conn.Db.MyAuth.User.RemoteQuery("WHERE id = 999"); + Wait(() => rolledBack.IsCompleted, "rollback verification"); + Require( + rolledBack.GetAwaiter().GetResult().Length == 0, + "Failed reducer committed a row" + ); + + var deleted = false; + conn.Db.MyAuth.User.OnDelete += (ctx, row) => + { + if (row.Id != 10) + return; + Require( + ctx.Db.MyAuth.User.Id.Find(10) == null + && ctx.Db.@class.User.Id.Find(10) != null, + "Deletion crossed namespace boundaries" + ); + deleted = true; + }; + conn.Reducers.MyAuth.Remove(10); + Wait(() => deleted, "namespaced deletion"); + Unsubscribe(subscription); + EmptyCache(); + var uncached = conn.Db.MyAuth.User.RemoteQuery(""); + Wait(() => uncached.IsCompleted, "unsubscribed RemoteQuery"); + Require( + uncached.GetAwaiter().GetResult().Single().Id == 2, + "Unsubscribed RemoteQuery result" + ); + EmptyCache(); + + var allApplied = false; + var all = conn.SubscriptionBuilder() + .OnApplied(_ => allApplied = true) + .OnError((_, error) => throw error) + .SubscribeToAllTables(); + Wait(() => allApplied, "subscribe-all initial rows"); + Require( + conn.Db.User.Count == 1 + && conn.Db.MyAuth.User.Count == 1 + && conn.Db.@class.User.Count == 2 + && conn.Db.ExtraRow.Count == 1 + && conn.Db.Users.Count == 1 + && conn.Db.MyAuth.Users.Count == 1 + && conn.Db.MyAuth.AnonymousUsers.Count == 1 + && conn.Db.MyAuth.QueryUsers.Count == 1 + && conn.Db.AuthUsers.Count == 1 + && conn.Db.QueryUsers.Count == 1 + && conn.Db.QueryUsersRight.Count == 1 + && conn.Db.QueryExtra.Count == 1, + "Subscribe-all omitted child tables or views" + ); + Require(notices == 1, "Event rows must not be replayed as persistent rows"); + Unsubscribe(all); + EmptyCache(); + Console.WriteLine("Namespace integration passed"); + } + finally + { + conn.Disconnect(); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/README.md b/sdks/csharp/examples~/regression-tests/namespaces/README.md new file mode 100644 index 00000000000..36edcfabff9 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/README.md @@ -0,0 +1,40 @@ +# Namespace Integration Test + +Runs a generated C# 9 / .NET 8 client against the .NET 10 module in +`modules/namespace-test-cs`. It uses `Accessor` as the namespace name throughout. + +The existing `sdks/csharp/tools~/run-regression-tests.sh 10` harness generates the +bindings, publishes a fresh `namespace-tests` database, and runs this client. +The namespace scenario is skipped in the .NET 8 **module** pass. CI already runs +both harness passes. + +For a focused run, from the repository root, with a local server running and local +C# packages configured as described in `sdks/csharp/DEVELOP.md`: + +```sh +cargo spacetime generate -y -l csharp -o sdks/csharp/examples~/regression-tests/namespaces/module_bindings --module-path modules/namespace-test-cs --build-options="--dotnet-version 10" +cargo spacetime publish --dotnet-version 10 -c -y --server local -p modules/namespace-test-cs namespace-tests +dotnet run --project sdks/csharp/examples~/regression-tests/namespaces/client.csproj +``` + +The publish command deletes existing data in the test database. Republish before +each client run. For a nondefault server, pass its URL to publish and set +`SPACETIMEDB_SERVER_URL` to that same URL for the client. + +Coverage: + +- Root and two mounted libraries with different row types named `User`, plus an + dependency automatically registered in `public`, without a namespace declaration. +- Explicit table names and a C# keyword namespace accessor. +- Typed subscriptions, filtered queries, both semijoin directions, and overlapping + subscriptions without duplicate rows or premature cache removal. +- Cross-library helper writes and callbacks observing the complete transaction. +- Same-named reducers/procedures in different namespaces, procedure success/error + callbacks, and child reducer failures forwarded to the root connection. +- Insert/update/delete callbacks, unique/B-tree indexes, and reducer rollback. +- Event rows, private-table access rejection, procedural/anonymous/query views. +- `RemoteQuery` result decoding and no subscription-cache population by one-off queries. +- Subscribe-all initial rows, no replay of past events, and unsubscribe cache cleanup. + +Assertions throw in both Debug and Release. Every asynchronous phase has a timeout. +The generated bindings are committed and regenerated through the normal CLI path. diff --git a/sdks/csharp/examples~/regression-tests/namespaces/client.csproj b/sdks/csharp/examples~/regression-tests/namespaces/client.csproj new file mode 100644 index 00000000000..1942262018f --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/client.csproj @@ -0,0 +1,13 @@ + + + Exe + net8.0 + 9 + enable + disable + true + + + + + diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs new file mode 100644 index 00000000000..db83438308f --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs @@ -0,0 +1,50 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteReducers : RemoteBase + { + internal RemoteReducers(global::SpacetimeDB.Types.DbConnection conn) : base(conn) { } + internal event Action? InternalOnUnhandledReducerError; + } + + public sealed partial class RemoteProcedures : RemoteBase + { + internal RemoteProcedures(global::SpacetimeDB.Types.DbConnection conn) : base(conn) { } + } + + public sealed partial class RemoteTables + { + internal RemoteTables(global::SpacetimeDB.Types.DbConnection conn, Action register) + { + register(AnonymousUsers = new(conn)); + register(Notice = new(conn)); + register(QueryUsers = new(conn)); + register(User = new(conn)); + register(Users = new(conn)); + } + } + public sealed class From + { + public global::SpacetimeDB.Table AnonymousUsers() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users"), new AnonymousUsersCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users")), new AnonymousUsersIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users"))); + public global::SpacetimeDB.Table Notice() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice"), new NoticeCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice")), new NoticeIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice"))); + public global::SpacetimeDB.Table QueryUsers() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users"), new QueryUsersCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users")), new QueryUsersIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users"))); + public global::SpacetimeDB.Table User() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users"), new UserCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users")), new UserIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users"))); + public global::SpacetimeDB.Table Users() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "users"), new UsersCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "users")), new UsersIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "users"))); + } + + public abstract partial class Reducer + { + private Reducer() { } + } + public abstract partial class Procedure + { + private Procedure() { } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/CountUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/CountUsers.g.cs new file mode 100644 index 00000000000..13beb94d9c6 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/CountUsers.g.cs @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteProcedures : RemoteBase + { + public void CountUsers(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalCountUsers((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalCountUsers(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.CountUsersArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class CountUsers + { + [DataMember(Name = "Value")] + public ulong Value; + + public CountUsers(ulong Value) + { + this.Value = Value; + } + + public CountUsers() + { + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class CountUsersArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "MyAuth.count_users"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadScore.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadScore.g.cs new file mode 100644 index 00000000000..d04f0c2dce2 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadScore.g.cs @@ -0,0 +1,76 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteProcedures : RemoteBase + { + public void ReadScore(uint id, ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalReadScore(id, (ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalReadScore(uint id, ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.ReadScoreArgs(id), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ReadScore + { + [DataMember(Name = "Value")] + public uint Value; + + public ReadScore(uint Value) + { + this.Value = Value; + } + + public ReadScore() + { + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ReadScoreArgs : Procedure, IProcedureArgs + { + [DataMember(Name = "id")] + public uint Id; + + public ReadScoreArgs(uint Id) + { + this.Id = Id; + } + + public ReadScoreArgs() + { + } + + string IProcedureArgs.ProcedureName => "MyAuth.read_score"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Add.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Add.g.cs new file mode 100644 index 00000000000..5cd8f874e95 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Add.g.cs @@ -0,0 +1,66 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void AddHandler(global::SpacetimeDB.Types.ReducerEventContext ctx, uint id); + public event AddHandler? OnAdd; + + public void Add(uint id) + { + conn.InternalCallReducer(new Reducer.Add(id)); + } + + public bool InvokeAdd(global::SpacetimeDB.Types.ReducerEventContext ctx, Reducer.Add args) + { + if (OnAdd == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnAdd( + ctx, + args.Id + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Add : global::SpacetimeDB.Types.Reducer, IReducerArgs + { + [DataMember(Name = "id")] + public uint Id; + + public Add(uint Id) + { + this.Id = Id; + } + + public Add() + { + } + + string IReducerArgs.ReducerName => "MyAuth.add"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Fail.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Fail.g.cs new file mode 100644 index 00000000000..23b574b280f --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Fail.g.cs @@ -0,0 +1,66 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void FailHandler(global::SpacetimeDB.Types.ReducerEventContext ctx, uint id); + public event FailHandler? OnFail; + + public void Fail(uint id) + { + conn.InternalCallReducer(new Reducer.Fail(id)); + } + + public bool InvokeFail(global::SpacetimeDB.Types.ReducerEventContext ctx, Reducer.Fail args) + { + if (OnFail == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnFail( + ctx, + args.Id + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Fail : global::SpacetimeDB.Types.Reducer, IReducerArgs + { + [DataMember(Name = "id")] + public uint Id; + + public Fail(uint Id) + { + this.Id = Id; + } + + public Fail() + { + } + + string IReducerArgs.ReducerName => "MyAuth.fail"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Remove.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Remove.g.cs new file mode 100644 index 00000000000..c8b74b56fe0 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Remove.g.cs @@ -0,0 +1,66 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void RemoveHandler(global::SpacetimeDB.Types.ReducerEventContext ctx, uint id); + public event RemoveHandler? OnRemove; + + public void Remove(uint id) + { + conn.InternalCallReducer(new Reducer.Remove(id)); + } + + public bool InvokeRemove(global::SpacetimeDB.Types.ReducerEventContext ctx, Reducer.Remove args) + { + if (OnRemove == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnRemove( + ctx, + args.Id + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Remove : global::SpacetimeDB.Types.Reducer, IReducerArgs + { + [DataMember(Name = "id")] + public uint Id; + + public Remove(uint Id) + { + this.Id = Id; + } + + public Remove() + { + } + + string IReducerArgs.ReducerName => "MyAuth.remove"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Update.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Update.g.cs new file mode 100644 index 00000000000..9ad92e8c57b --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Update.g.cs @@ -0,0 +1,73 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void UpdateHandler(global::SpacetimeDB.Types.ReducerEventContext ctx, uint id, uint score); + public event UpdateHandler? OnUpdate; + + public void Update(uint id, uint score) + { + conn.InternalCallReducer(new Reducer.Update(id, score)); + } + + public bool InvokeUpdate(global::SpacetimeDB.Types.ReducerEventContext ctx, Reducer.Update args) + { + if (OnUpdate == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnUpdate( + ctx, + args.Id, + args.Score + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Update : global::SpacetimeDB.Types.Reducer, IReducerArgs + { + [DataMember(Name = "id")] + public uint Id; + [DataMember(Name = "score")] + public uint Score; + + public Update( + uint Id, + uint Score + ) + { + this.Id = Id; + this.Score = Score; + } + + public Update() + { + } + + string IReducerArgs.ReducerName => "MyAuth.update"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs new file mode 100644 index 00000000000..65b28e43872 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs @@ -0,0 +1,48 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteTables + { + public sealed class AnonymousUsersHandle : RemoteTableHandle + { + public override string RemoteTableName => "MyAuth.anonymous_users"; + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users"); + + internal AnonymousUsersHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) + { + } + } + + public readonly AnonymousUsersHandle AnonymousUsers; + } + + public sealed class AnonymousUsersCols + { + public global::SpacetimeDB.Col Id { get; } + public global::SpacetimeDB.Col Score { get; } + + public AnonymousUsersCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + Score = new global::SpacetimeDB.Col(tableName, "score"); + } + } + + public sealed class AnonymousUsersIxCols + { + + public AnonymousUsersIxCols(global::SpacetimeDB.SqlTableName tableName) + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs new file mode 100644 index 00000000000..89215cafc7f --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs @@ -0,0 +1,46 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteTables + { + public sealed class NoticeHandle : RemoteEventTableHandle + { + public override string RemoteTableName => "MyAuth.notice"; + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice"); + + internal NoticeHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) + { + } + } + + public readonly NoticeHandle Notice; + } + + public sealed class NoticeCols + { + public global::SpacetimeDB.Col Id { get; } + + public NoticeCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + } + } + + public sealed class NoticeIxCols + { + + public NoticeIxCols(global::SpacetimeDB.SqlTableName tableName) + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs new file mode 100644 index 00000000000..f50754f4634 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs @@ -0,0 +1,62 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteTables + { + public sealed class QueryUsersHandle : RemoteTableHandle + { + public override string RemoteTableName => "MyAuth.query_users"; + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users"); + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override uint GetKey(User row) => row.Id; + + public IdUniqueIndex(QueryUsersHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + internal QueryUsersHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) + { + Id = new(this); + } + + protected override object GetPrimaryKey(User row) => row.Id; + } + + public readonly QueryUsersHandle QueryUsers; + } + + public sealed class QueryUsersCols + { + public global::SpacetimeDB.Col Id { get; } + public global::SpacetimeDB.Col Score { get; } + + public QueryUsersCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + Score = new global::SpacetimeDB.Col(tableName, "score"); + } + } + + public sealed class QueryUsersIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + + public QueryUsersIxCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs new file mode 100644 index 00000000000..472635e390f --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs @@ -0,0 +1,74 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteTables + { + public sealed class UserHandle : RemoteTableHandle + { + public override string RemoteTableName => "MyAuth.auth_users"; + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users"); + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override uint GetKey(User row) => row.Id; + + public IdUniqueIndex(UserHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + public sealed class ByScoreIndex : BTreeIndexBase + { + protected override uint GetKey(User row) => row.Score; + + public ByScoreIndex(UserHandle table) : base(table) { } + } + + public readonly ByScoreIndex ByScore; + + internal UserHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) + { + Id = new(this); + ByScore = new(this); + } + + protected override object GetPrimaryKey(User row) => row.Id; + } + + public readonly UserHandle User; + } + + public sealed class UserCols + { + public global::SpacetimeDB.Col Id { get; } + public global::SpacetimeDB.Col Score { get; } + + public UserCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + Score = new global::SpacetimeDB.Col(tableName, "score"); + } + } + + public sealed class UserIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + public global::SpacetimeDB.IxCol Score { get; } + + public UserIxCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + Score = new global::SpacetimeDB.IxCol(tableName, "score"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs new file mode 100644 index 00000000000..ff067caa321 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs @@ -0,0 +1,48 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteTables + { + public sealed class UsersHandle : RemoteTableHandle + { + public override string RemoteTableName => "MyAuth.users"; + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "users"); + + internal UsersHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) + { + } + } + + public readonly UsersHandle Users; + } + + public sealed class UsersCols + { + public global::SpacetimeDB.Col Id { get; } + public global::SpacetimeDB.Col Score { get; } + + public UsersCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + Score = new global::SpacetimeDB.Col(tableName, "score"); + } + } + + public sealed class UsersIxCols + { + + public UsersIxCols(global::SpacetimeDB.SqlTableName tableName) + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/Notice.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/Notice.g.cs new file mode 100644 index 00000000000..03be173cad2 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/Notice.g.cs @@ -0,0 +1,28 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Notice + { + [DataMember(Name = "id")] + public uint Id; + + public Notice(uint Id) + { + this.Id = Id; + } + + public Notice() + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/Secret.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/Secret.g.cs new file mode 100644 index 00000000000..31cff985b59 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/Secret.g.cs @@ -0,0 +1,28 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Secret + { + [DataMember(Name = "id")] + public uint Id; + + public Secret(uint Id) + { + this.Id = Id; + } + + public Secret() + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/User.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/User.g.cs new file mode 100644 index 00000000000..48be9c0f4c6 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/User.g.cs @@ -0,0 +1,34 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class User + { + [DataMember(Name = "id")] + public uint Id; + [DataMember(Name = "score")] + public uint Score; + + public User( + uint Id, + uint Score + ) + { + this.Id = Id; + this.Score = Score; + } + + public User() + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/CountUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/CountUsers.g.cs new file mode 100644 index 00000000000..a3143fd4396 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/CountUsers.g.cs @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteProcedures : RemoteBase + { + public void CountUsers(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalCountUsers((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalCountUsers(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.CountUsersArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class CountUsers + { + [DataMember(Name = "Value")] + public ulong Value; + + public CountUsers(ulong Value) + { + this.Value = Value; + } + + public CountUsers() + { + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class CountUsersArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "count_users"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/Exercise.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/Exercise.g.cs new file mode 100644 index 00000000000..81bf38f0b86 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/Exercise.g.cs @@ -0,0 +1,53 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void ExerciseHandler(ReducerEventContext ctx); + public event ExerciseHandler? OnExercise; + + public void Exercise() + { + conn.InternalCallReducer(new Reducer.Exercise()); + } + + public bool InvokeExercise(ReducerEventContext ctx, Reducer.Exercise args) + { + if (OnExercise == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnExercise( + ctx + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Exercise : Reducer, IReducerArgs + { + string IReducerArgs.ReducerName => "exercise"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/Extra.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/Extra.g.cs new file mode 100644 index 00000000000..94e0c8c3e11 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/Extra.g.cs @@ -0,0 +1,53 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void ExtraHandler(ReducerEventContext ctx); + public event ExtraHandler? OnExtra; + + public void Extra() + { + conn.InternalCallReducer(new Reducer.Extra()); + } + + public bool InvokeExtra(ReducerEventContext ctx, Reducer.Extra args) + { + if (OnExtra == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnExtra( + ctx + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Extra : Reducer, IReducerArgs + { + string IReducerArgs.ReducerName => "extra"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs new file mode 100644 index 00000000000..02ffeaa503c --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs @@ -0,0 +1,681 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +// This was generated using spacetimedb cli version 2.10.1 (commit bc86b7fc7cf3f6a7408e64cf13cab594c20afbc2). + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public global::SpacetimeDB.Types.@class.RemoteReducers @class { get; } + public global::SpacetimeDB.Types.@MyAuth.RemoteReducers @MyAuth { get; } + internal RemoteReducers(DbConnection conn) : base(conn) + { + @class = new(conn); + @class.InternalOnUnhandledReducerError += (ctx, error) => InternalOnUnhandledReducerError?.Invoke(ctx, error); + @MyAuth = new(conn); + @MyAuth.InternalOnUnhandledReducerError += (ctx, error) => InternalOnUnhandledReducerError?.Invoke(ctx, error); + } + internal event Action? InternalOnUnhandledReducerError; + } + + public sealed partial class RemoteProcedures : RemoteBase + { + public global::SpacetimeDB.Types.@class.RemoteProcedures @class { get; } + public global::SpacetimeDB.Types.@MyAuth.RemoteProcedures @MyAuth { get; } + internal RemoteProcedures(DbConnection conn) : base(conn) + { + @class = new(conn); + @MyAuth = new(conn); + } + } + + public sealed partial class RemoteTables : RemoteTablesBase + { + public global::SpacetimeDB.Types.@class.RemoteTables @class { get; } + public global::SpacetimeDB.Types.@MyAuth.RemoteTables @MyAuth { get; } + public RemoteTables(DbConnection conn) + { + AddTable(AuthUsers = new(conn)); + AddTable(ExtraRow = new(conn)); + AddTable(ExtraRows = new(conn)); + AddTable(QueryExtra = new(conn)); + AddTable(QueryUsers = new(conn)); + AddTable(QueryUsersRight = new(conn)); + AddTable(User = new(conn)); + AddTable(Users = new(conn)); + @class = new(conn, AddTable); + @MyAuth = new(conn, AddTable); + } + } + + + public interface IRemoteDbContext : IDbContext + { + public event Action? OnUnhandledReducerError; + } + + public sealed class EventContext : IEventContext, IRemoteDbContext + { + private readonly DbConnection conn; + + /// + /// The event that caused this callback to run. + /// + public readonly Event Event; + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to procedures defined by the module. + /// + /// The returned RemoteProcedures will have a method to invoke each procedure defined by the module, + /// with a callback for when the procedure completes and returns a value. + /// + public RemoteProcedures Procedures => conn.Procedures; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + /// + /// Register a callback to be called when a reducer with no handler returns an error. + /// + public event Action? OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } + + internal EventContext(DbConnection conn, Event Event) + { + this.conn = conn; + this.Event = Event; + } + } + + public sealed class ReducerEventContext : IReducerEventContext, IRemoteDbContext + { + private readonly DbConnection conn; + /// + /// The reducer event that caused this callback to run. + /// + public readonly ReducerEvent Event; + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to procedures defined by the module. + /// + /// The returned RemoteProcedures will have a method to invoke each procedure defined by the module, + /// with a callback for when the procedure completes and returns a value. + /// + public RemoteProcedures Procedures => conn.Procedures; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + /// + /// Register a callback to be called when a reducer with no handler returns an error. + /// + public event Action? OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } + + internal ReducerEventContext(DbConnection conn, ReducerEvent reducerEvent) + { + this.conn = conn; + Event = reducerEvent; + } + } + + public sealed class ErrorContext : IErrorContext, IRemoteDbContext + { + private readonly DbConnection conn; + /// + /// The Exception that caused this error callback to be run. + /// + public readonly Exception Event; + Exception IErrorContext.Event + { + get + { + return Event; + } + } + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to procedures defined by the module. + /// + /// The returned RemoteProcedures will have a method to invoke each procedure defined by the module, + /// with a callback for when the procedure completes and returns a value. + /// + public RemoteProcedures Procedures => conn.Procedures; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + /// + /// Register a callback to be called when a reducer with no handler returns an error. + /// + public event Action? OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } + + internal ErrorContext(DbConnection conn, Exception error) + { + this.conn = conn; + Event = error; + } + } + + public sealed class SubscriptionEventContext : ISubscriptionEventContext, IRemoteDbContext + { + private readonly DbConnection conn; + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to procedures defined by the module. + /// + /// The returned RemoteProcedures will have a method to invoke each procedure defined by the module, + /// with a callback for when the procedure completes and returns a value. + /// + public RemoteProcedures Procedures => conn.Procedures; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + /// + /// Register a callback to be called when a reducer with no handler returns an error. + /// + public event Action? OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } + + internal SubscriptionEventContext(DbConnection conn) + { + this.conn = conn; + } + } + + public sealed class ProcedureEventContext : IProcedureEventContext, IRemoteDbContext + { + private readonly DbConnection conn; + /// + /// The procedure event that caused this callback to run. + /// + public readonly ProcedureEvent Event; + + /// + /// Access to tables in the client cache, which stores a read-only replica of the remote database state. + /// + /// The returned DbView will have a method to access each table defined by the module. + /// + public RemoteTables Db => conn.Db; + /// + /// Access to reducers defined by the module. + /// + /// The returned RemoteReducers will have a method to invoke each reducer defined by the module, + /// plus methods for adding and removing callbacks on each of those reducers. + /// + public RemoteReducers Reducers => conn.Reducers; + /// + /// Access to procedures defined by the module. + /// + /// The returned RemoteProcedures will have a method to invoke each procedure defined by the module, + /// with a callback for when the procedure completes and returns a value. + /// + public RemoteProcedures Procedures => conn.Procedures; + /// + /// Returns true if the connection is active, i.e. has not yet disconnected. + /// + public bool IsActive => conn.IsActive; + /// + /// Close the connection. + /// + /// Throws an error if the connection is already closed. + /// + public void Disconnect() + { + conn.Disconnect(); + } + /// + /// Start building a subscription. + /// + /// A builder-pattern constructor for subscribing to queries, + /// causing matching rows to be replicated into the client cache. + public SubscriptionBuilder SubscriptionBuilder() => conn.SubscriptionBuilder(); + /// + /// Get the Identity of this connection. + /// + /// This method returns null if the connection was constructed anonymously + /// and we have not yet received our newly-generated Identity from the host. + /// + public Identity? Identity => conn.Identity; + /// + /// Get this connection's ConnectionId. + /// + public ConnectionId ConnectionId => conn.ConnectionId; + /// + /// Register a callback to be called when a reducer with no handler returns an error. + /// + public event Action? OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } + + internal ProcedureEventContext(DbConnection conn, ProcedureEvent Event) + { + this.conn = conn; + this.Event = Event; + } + } + + /// + /// Builder-pattern constructor for subscription queries. + /// + public sealed class SubscriptionBuilder + { + private readonly IDbConnection conn; + + private event Action? Applied; + private event Action? Error; + + /// + /// Private API, use conn.SubscriptionBuilder() instead. + /// + public SubscriptionBuilder(IDbConnection conn) + { + this.conn = conn; + } + + /// + /// Register a callback to run when the subscription is applied. + /// + public SubscriptionBuilder OnApplied( + Action callback + ) + { + Applied += callback; + return this; + } + + /// + /// Register a callback to run when the subscription fails. + /// + /// Note that this callback may run either when attempting to apply the subscription, + /// in which case Self::on_applied will never run, + /// or later during the subscription's lifetime if the module's interface changes, + /// in which case Self::on_applied may have already run. + /// + public SubscriptionBuilder OnError( + Action callback + ) + { + Error += callback; + return this; + } + + /// + /// Add a typed query to this subscription. + /// + /// This is the entry point for building subscriptions without writing SQL by hand. + /// Once a typed query is added, only typed queries may follow (SQL and typed queries cannot be mixed). + /// + public TypedSubscriptionBuilder AddQuery( + Func> build + ) + { + var typed = new TypedSubscriptionBuilder(conn, Applied, Error); + return typed.AddQuery(build); + } + + /// + /// Subscribe to the following SQL queries. + /// + /// This method returns immediately, with the data not yet added to the DbConnection. + /// The provided callbacks will be invoked once the data is returned from the remote server. + /// Data from all the provided queries will be returned at the same time. + /// + /// See the SpacetimeDB SQL docs for more information on SQL syntax: + /// https://spacetimedb.com/docs/sql + /// + public SubscriptionHandle Subscribe( + string[] querySqls + ) => new(conn, Applied, Error, querySqls); + + /// + /// Subscribe to all rows from all tables. + /// + /// This method is intended as a convenience + /// for applications where client-side memory use and network bandwidth are not concerns. + /// Applications where these resources are a constraint + /// should register more precise queries via Self.Subscribe + /// in order to replicate only the subset of data which the client needs to function. + /// + /// This method should not be combined with Self.Subscribe on the same DbConnection. + /// A connection may either Self.Subscribe to particular queries, + /// or Self.SubscribeToAllTables, but not both. + /// Attempting to call Self.Subscribe + /// on a DbConnection that has previously used Self.SubscribeToAllTables, + /// or vice versa, may misbehave in any number of ways, + /// including dropping subscriptions, corrupting the client cache, or panicking. + /// + public SubscriptionHandle SubscribeToAllTables() => + new(conn, Applied, Error, QueryBuilder.AllTablesSqlQueries()); + } + + public sealed class SubscriptionHandle : SubscriptionHandleBase + { + /// + /// Internal API. Construct SubscriptionHandles using conn.SubscriptionBuilder. + /// + public SubscriptionHandle( + IDbConnection conn, + Action? onApplied, + Action? onError, + string[] querySqls + ) : base(conn, onApplied, onError, querySqls) + { } + } + + public sealed class QueryBuilder + { + public From From { get; } = new(); + + internal static string[] AllTablesSqlQueries() => new string[] + { + new QueryBuilder().From.AuthUsers().ToSql(), + new QueryBuilder().From.ExtraRow().ToSql(), + new QueryBuilder().From.ExtraRows().ToSql(), + new QueryBuilder().From.QueryExtra().ToSql(), + new QueryBuilder().From.QueryUsers().ToSql(), + new QueryBuilder().From.QueryUsersRight().ToSql(), + new QueryBuilder().From.User().ToSql(), + new QueryBuilder().From.Users().ToSql(), + new QueryBuilder().From.@class.User().ToSql(), + new QueryBuilder().From.@MyAuth.Notice().ToSql(), + new QueryBuilder().From.@MyAuth.User().ToSql(), + new QueryBuilder().From.@MyAuth.QueryUsers().ToSql(), + new QueryBuilder().From.@MyAuth.Users().ToSql(), + new QueryBuilder().From.@MyAuth.AnonymousUsers().ToSql(), + } + ; + } + + public sealed class From + { + public global::SpacetimeDB.Types.@class.From @class { get; } = new(); + public global::SpacetimeDB.Types.@MyAuth.From @MyAuth { get; } = new(); + public global::SpacetimeDB.Table AuthUsers() => new("auth_users", new AuthUsersCols("auth_users"), new AuthUsersIxCols("auth_users")); + public global::SpacetimeDB.Table ExtraRow() => new("extra_row", new ExtraRowCols("extra_row"), new ExtraRowIxCols("extra_row")); + public global::SpacetimeDB.Table ExtraRows() => new("extra_rows", new ExtraRowsCols("extra_rows"), new ExtraRowsIxCols("extra_rows")); + public global::SpacetimeDB.Table QueryExtra() => new("query_extra", new QueryExtraCols("query_extra"), new QueryExtraIxCols("query_extra")); + public global::SpacetimeDB.Table QueryUsers() => new("query_users", new QueryUsersCols("query_users"), new QueryUsersIxCols("query_users")); + public global::SpacetimeDB.Table QueryUsersRight() => new("query_users_right", new QueryUsersRightCols("query_users_right"), new QueryUsersRightIxCols("query_users_right")); + public global::SpacetimeDB.Table User() => new("user", new UserCols("user"), new UserIxCols("user")); + public global::SpacetimeDB.Table Users() => new("users", new UsersCols("users"), new UsersIxCols("users")); + } + + public sealed class TypedSubscriptionBuilder + { + private readonly IDbConnection conn; + private Action? Applied; + private Action? Error; + private readonly List querySqls = new(); + + internal TypedSubscriptionBuilder(IDbConnection conn, Action? applied, Action? error) + { + this.conn = conn; + Applied = applied; + Error = error; + } + + public TypedSubscriptionBuilder OnApplied(Action callback) + { + Applied += callback; + return this; + } + + public TypedSubscriptionBuilder OnError(Action callback) + { + Error += callback; + return this; + } + + public TypedSubscriptionBuilder AddQuery(Func> build) + { + var qb = new QueryBuilder(); + querySqls.Add(build(qb).ToSql()); + return this; + } + + public SubscriptionHandle Subscribe() => new(conn, Applied, Error, querySqls.ToArray()); + } + + public abstract partial class Reducer + { + private protected Reducer() { } + } + + public abstract partial class Procedure + { + private Procedure() { } + } + + public sealed class DbConnection : DbConnectionBase + { + public override RemoteTables Db { get; } + public readonly RemoteReducers Reducers; + public readonly RemoteProcedures Procedures; + + public DbConnection() + { + Db = new(this); + Reducers = new(this); + Procedures = new(this); + } + + protected override IEventContext ToEventContext(Event Event) => + new EventContext(this, Event); + + protected override IReducerEventContext ToReducerEventContext(ReducerEvent reducerEvent) => + new ReducerEventContext(this, reducerEvent); + + protected override ISubscriptionEventContext MakeSubscriptionEventContext() => + new SubscriptionEventContext(this); + + protected override IErrorContext ToErrorContext(Exception exception) => + new ErrorContext(this, exception); + + protected override IProcedureEventContext ToProcedureEventContext(ProcedureEvent procedureEvent) => + new ProcedureEventContext(this, procedureEvent); + + protected override bool Dispatch(IReducerEventContext context, Reducer reducer) + { + var eventContext = (ReducerEventContext)context; + return reducer switch + { + Reducer.Exercise args => Reducers.InvokeExercise(eventContext, args), + Reducer.Extra args => Reducers.InvokeExtra(eventContext, args), + global::SpacetimeDB.Types.@class.Reducer.Add args => Reducers.@class.InvokeAdd(eventContext, args), + global::SpacetimeDB.Types.@MyAuth.Reducer.Add args => Reducers.@MyAuth.InvokeAdd(eventContext, args), + global::SpacetimeDB.Types.@MyAuth.Reducer.Fail args => Reducers.@MyAuth.InvokeFail(eventContext, args), + global::SpacetimeDB.Types.@MyAuth.Reducer.Remove args => Reducers.@MyAuth.InvokeRemove(eventContext, args), + global::SpacetimeDB.Types.@MyAuth.Reducer.Update args => Reducers.@MyAuth.InvokeUpdate(eventContext, args), + _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") + }; + } + + public SubscriptionBuilder SubscriptionBuilder() => new(this); + public event Action OnUnhandledReducerError + { + add => Reducers.InternalOnUnhandledReducerError += value; + remove => Reducers.InternalOnUnhandledReducerError -= value; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/AuthUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/AuthUsers.g.cs new file mode 100644 index 00000000000..17cebd8cd11 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/AuthUsers.g.cs @@ -0,0 +1,45 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class AuthUsersHandle : RemoteTableHandle + { + public override string RemoteTableName => "auth_users"; + + internal AuthUsersHandle(DbConnection conn) : base(conn) + { + } + } + + public readonly AuthUsersHandle AuthUsers; + } + + public sealed class AuthUsersCols + { + public global::SpacetimeDB.Col Score { get; } + + public AuthUsersCols(string tableName) + { + Score = new global::SpacetimeDB.Col(tableName, "score"); + } + } + + public sealed class AuthUsersIxCols + { + + public AuthUsersIxCols(string tableName) + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/ExtraRow.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/ExtraRow.g.cs new file mode 100644 index 00000000000..bf5a18779a9 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/ExtraRow.g.cs @@ -0,0 +1,59 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class ExtraRowHandle : RemoteTableHandle + { + public override string RemoteTableName => "extra_row"; + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override uint GetKey(ExtraRow row) => row.Id; + + public IdUniqueIndex(ExtraRowHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + internal ExtraRowHandle(DbConnection conn) : base(conn) + { + Id = new(this); + } + + protected override object GetPrimaryKey(ExtraRow row) => row.Id; + } + + public readonly ExtraRowHandle ExtraRow; + } + + public sealed class ExtraRowCols + { + public global::SpacetimeDB.Col Id { get; } + + public ExtraRowCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + } + } + + public sealed class ExtraRowIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + + public ExtraRowIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/ExtraRows.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/ExtraRows.g.cs new file mode 100644 index 00000000000..2783f517464 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/ExtraRows.g.cs @@ -0,0 +1,45 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class ExtraRowsHandle : RemoteTableHandle + { + public override string RemoteTableName => "extra_rows"; + + internal ExtraRowsHandle(DbConnection conn) : base(conn) + { + } + } + + public readonly ExtraRowsHandle ExtraRows; + } + + public sealed class ExtraRowsCols + { + public global::SpacetimeDB.Col Id { get; } + + public ExtraRowsCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + } + } + + public sealed class ExtraRowsIxCols + { + + public ExtraRowsIxCols(string tableName) + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/QueryExtra.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/QueryExtra.g.cs new file mode 100644 index 00000000000..d4ed4e5e190 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/QueryExtra.g.cs @@ -0,0 +1,59 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class QueryExtraHandle : RemoteTableHandle + { + public override string RemoteTableName => "query_extra"; + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override uint GetKey(ExtraRow row) => row.Id; + + public IdUniqueIndex(QueryExtraHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + internal QueryExtraHandle(DbConnection conn) : base(conn) + { + Id = new(this); + } + + protected override object GetPrimaryKey(ExtraRow row) => row.Id; + } + + public readonly QueryExtraHandle QueryExtra; + } + + public sealed class QueryExtraCols + { + public global::SpacetimeDB.Col Id { get; } + + public QueryExtraCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + } + } + + public sealed class QueryExtraIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + + public QueryExtraIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/QueryUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/QueryUsers.g.cs new file mode 100644 index 00000000000..3d6fd0ffeb1 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/QueryUsers.g.cs @@ -0,0 +1,59 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class QueryUsersHandle : RemoteTableHandle + { + public override string RemoteTableName => "query_users"; + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override uint GetKey(User row) => row.Id; + + public IdUniqueIndex(QueryUsersHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + internal QueryUsersHandle(DbConnection conn) : base(conn) + { + Id = new(this); + } + + protected override object GetPrimaryKey(User row) => row.Id; + } + + public readonly QueryUsersHandle QueryUsers; + } + + public sealed class QueryUsersCols + { + public global::SpacetimeDB.Col Id { get; } + + public QueryUsersCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + } + } + + public sealed class QueryUsersIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + + public QueryUsersIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/QueryUsersRight.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/QueryUsersRight.g.cs new file mode 100644 index 00000000000..789c48e05ee --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/QueryUsersRight.g.cs @@ -0,0 +1,59 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class QueryUsersRightHandle : RemoteTableHandle + { + public override string RemoteTableName => "query_users_right"; + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override uint GetKey(User row) => row.Id; + + public IdUniqueIndex(QueryUsersRightHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + internal QueryUsersRightHandle(DbConnection conn) : base(conn) + { + Id = new(this); + } + + protected override object GetPrimaryKey(User row) => row.Id; + } + + public readonly QueryUsersRightHandle QueryUsersRight; + } + + public sealed class QueryUsersRightCols + { + public global::SpacetimeDB.Col Id { get; } + + public QueryUsersRightCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + } + } + + public sealed class QueryUsersRightIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + + public QueryUsersRightIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/User.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/User.g.cs new file mode 100644 index 00000000000..36347fddc14 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/User.g.cs @@ -0,0 +1,59 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class UserHandle : RemoteTableHandle + { + public override string RemoteTableName => "user"; + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override uint GetKey(User row) => row.Id; + + public IdUniqueIndex(UserHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + internal UserHandle(DbConnection conn) : base(conn) + { + Id = new(this); + } + + protected override object GetPrimaryKey(User row) => row.Id; + } + + public readonly UserHandle User; + } + + public sealed class UserCols + { + public global::SpacetimeDB.Col Id { get; } + + public UserCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + } + } + + public sealed class UserIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + + public UserIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/Users.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/Users.g.cs new file mode 100644 index 00000000000..bf10755fee7 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Tables/Users.g.cs @@ -0,0 +1,45 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class UsersHandle : RemoteTableHandle + { + public override string RemoteTableName => "users"; + + internal UsersHandle(DbConnection conn) : base(conn) + { + } + } + + public readonly UsersHandle Users; + } + + public sealed class UsersCols + { + public global::SpacetimeDB.Col Id { get; } + + public UsersCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + } + } + + public sealed class UsersIxCols + { + + public UsersIxCols(string tableName) + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Types/AuthSummary.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Types/AuthSummary.g.cs new file mode 100644 index 00000000000..31c6b653b03 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Types/AuthSummary.g.cs @@ -0,0 +1,28 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class AuthSummary + { + [DataMember(Name = "score")] + public uint Score; + + public AuthSummary(uint Score) + { + this.Score = Score; + } + + public AuthSummary() + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Types/ExtraRow.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Types/ExtraRow.g.cs new file mode 100644 index 00000000000..1759fe6f549 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Types/ExtraRow.g.cs @@ -0,0 +1,28 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ExtraRow + { + [DataMember(Name = "id")] + public uint Id; + + public ExtraRow(uint Id) + { + this.Id = Id; + } + + public ExtraRow() + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Types/User.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Types/User.g.cs new file mode 100644 index 00000000000..d9e5a3733aa --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Types/User.g.cs @@ -0,0 +1,28 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class User + { + [DataMember(Name = "id")] + public uint Id; + + public User(uint Id) + { + this.Id = Id; + } + + public User() + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Namespace.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Namespace.g.cs new file mode 100644 index 00000000000..8d9731616d7 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Namespace.g.cs @@ -0,0 +1,42 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; + +namespace SpacetimeDB.Types.@class +{ + public sealed partial class RemoteReducers : RemoteBase + { + internal RemoteReducers(global::SpacetimeDB.Types.DbConnection conn) : base(conn) { } + internal event Action? InternalOnUnhandledReducerError; + } + + public sealed partial class RemoteProcedures : RemoteBase + { + internal RemoteProcedures(global::SpacetimeDB.Types.DbConnection conn) : base(conn) { } + } + + public sealed partial class RemoteTables + { + internal RemoteTables(global::SpacetimeDB.Types.DbConnection conn, Action register) + { + register(User = new(conn)); + } + } + public sealed class From + { + public global::SpacetimeDB.Table User() => new(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "user"), new UserCols(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "user")), new UserIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "user"))); + } + + public abstract partial class Reducer + { + private Reducer() { } + } + public abstract partial class Procedure + { + private Procedure() { } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Procedures/CountUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Procedures/CountUsers.g.cs new file mode 100644 index 00000000000..ed009b4d43c --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Procedures/CountUsers.g.cs @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@class +{ + public sealed partial class RemoteProcedures : RemoteBase + { + public void CountUsers(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalCountUsers((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalCountUsers(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.CountUsersArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class CountUsers + { + [DataMember(Name = "Value")] + public ulong Value; + + public CountUsers(ulong Value) + { + this.Value = Value; + } + + public CountUsers() + { + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class CountUsersArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "class.count_users"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Reducers/Add.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Reducers/Add.g.cs new file mode 100644 index 00000000000..7396fd1840a --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Reducers/Add.g.cs @@ -0,0 +1,66 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@class +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void AddHandler(global::SpacetimeDB.Types.ReducerEventContext ctx, uint id); + public event AddHandler? OnAdd; + + public void Add(uint id) + { + conn.InternalCallReducer(new Reducer.Add(id)); + } + + public bool InvokeAdd(global::SpacetimeDB.Types.ReducerEventContext ctx, Reducer.Add args) + { + if (OnAdd == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnAdd( + ctx, + args.Id + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class Add : global::SpacetimeDB.Types.Reducer, IReducerArgs + { + [DataMember(Name = "id")] + public uint Id; + + public Add(uint Id) + { + this.Id = Id; + } + + public Add() + { + } + + string IReducerArgs.ReducerName => "class.add"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/User.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/User.g.cs new file mode 100644 index 00000000000..c769b9fadbe --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/User.g.cs @@ -0,0 +1,62 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@class +{ + public sealed partial class RemoteTables + { + public sealed class UserHandle : RemoteTableHandle + { + public override string RemoteTableName => "class.user"; + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "user"); + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override uint GetKey(User row) => row.Id; + + public IdUniqueIndex(UserHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + internal UserHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) + { + Id = new(this); + } + + protected override object GetPrimaryKey(User row) => row.Id; + } + + public readonly UserHandle User; + } + + public sealed class UserCols + { + public global::SpacetimeDB.Col Id { get; } + public global::SpacetimeDB.Col Message { get; } + + public UserCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + Message = new global::SpacetimeDB.Col(tableName, "message"); + } + } + + public sealed class UserIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + + public UserIxCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/User.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/User.g.cs new file mode 100644 index 00000000000..7b1c4914ee6 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/User.g.cs @@ -0,0 +1,35 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@class +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class User + { + [DataMember(Name = "id")] + public uint Id; + [DataMember(Name = "message")] + public string Message; + + public User( + uint Id, + string Message + ) + { + this.Id = Id; + this.Message = Message; + } + + public User() + { + this.Message = ""; + } + } +} diff --git a/sdks/csharp/tools~/gen-regression-tests.sh b/sdks/csharp/tools~/gen-regression-tests.sh index d7bd005cf45..1bf296898b5 100755 --- a/sdks/csharp/tools~/gen-regression-tests.sh +++ b/sdks/csharp/tools~/gen-regression-tests.sh @@ -86,3 +86,7 @@ fi cargo spacetime generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/server" "${BUILD_OPTIONS[@]}" cargo spacetime generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/republishing/client/module_bindings" --module-path "$SDK_PATH/examples~/regression-tests/republishing/server-republish" "${BUILD_OPTIONS[@]}" cargo spacetime generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/procedure-client/module_bindings" --module-path "$STDB_PATH/modules/sdk-test-procedure" "${BUILD_OPTIONS[@]}" + +if [ -z "$DOTNET_VERSION" ] || [ "$DOTNET_VERSION" = "10" ]; then + cargo spacetime generate -y -l csharp -o "$SDK_PATH/examples~/regression-tests/namespaces/module_bindings" --module-path "$STDB_PATH/modules/namespace-test-cs" --build-options="--dotnet-version 10" +fi diff --git a/sdks/csharp/tools~/run-regression-tests.sh b/sdks/csharp/tools~/run-regression-tests.sh index 8415f319ee7..b2cb3542c7b 100644 --- a/sdks/csharp/tools~/run-regression-tests.sh +++ b/sdks/csharp/tools~/run-regression-tests.sh @@ -130,4 +130,10 @@ for dotnet_version in "${DOTNET_VERSIONS[@]}"; do run_client "$SDK_PATH/examples~/regression-tests/client" "$dotnet_version" run_client "$SDK_PATH/examples~/regression-tests/republishing/client" "$dotnet_version" run_client "$SDK_PATH/examples~/regression-tests/procedure-client" "$dotnet_version" + + if [ "$dotnet_version" = "10" ]; then + cargo spacetime publish --dotnet-version 10 -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$STDB_PATH/modules/namespace-test-cs" namespace-tests + # The module needs .NET 10; its generated client deliberately stays on C# 9 / .NET 8. + run_client "$SDK_PATH/examples~/regression-tests/namespaces" 8 + fi done From d18ecdd905fead1394d4070cb677c110d60bf01a Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Fri, 18 Sep 2026 07:11:29 -0500 Subject: [PATCH 12/49] Scheduled reducers/procedures inside a namespace --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 61 +++++++ .../Module#Reducers.DemoProcedure.verified.cs | 2 +- .../Module#Reducers.DemoReducer.verified.cs | 2 +- crates/bindings-csharp/Codegen/Module.cs | 14 +- crates/codegen/src/csharp.rs | 6 +- crates/codegen/tests/codegen.rs | 30 +++- .../tests/csharp-namespaces/Program.cs | 19 +- .../libraries/AuditLib/Scheduled.cs | 164 ++++++++++++++++++ .../libraries/AuthLib/Scheduled.cs | 164 ++++++++++++++++++ .../regression-tests/namespaces/Program.cs | 116 ++++++++++++- .../regression-tests/namespaces/README.md | 4 + .../module_bindings/MyAuth/Namespace.g.cs | 2 + .../MyAuth/Reducers/CancelSchedules.g.cs | 53 ++++++ .../MyAuth/Reducers/StartSchedules.g.cs | 53 ++++++ .../MyAuth/Tables/ScheduleResult.g.cs | 68 ++++++++ .../MyAuth/Types/ProcedureJob.g.cs | 43 +++++ .../MyAuth/Types/ReducerJob.g.cs | 43 +++++ .../MyAuth/Types/ScheduleResult.g.cs | 47 +++++ .../module_bindings/SpacetimeDBClient.g.cs | 10 +- .../module_bindings/class/Namespace.g.cs | 2 + .../class/Reducers/CancelSchedules.g.cs | 53 ++++++ .../class/Reducers/StartSchedules.g.cs | 53 ++++++ .../class/Tables/ScheduleResult.g.cs | 68 ++++++++ .../class/Types/ProcedureJob.g.cs | 43 +++++ .../class/Types/ReducerJob.g.cs | 43 +++++ .../class/Types/ScheduleResult.g.cs | 47 +++++ 26 files changed, 1183 insertions(+), 27 deletions(-) create mode 100644 modules/namespace-test-cs/libraries/AuditLib/Scheduled.cs create mode 100644 modules/namespace-test-cs/libraries/AuthLib/Scheduled.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/CancelSchedules.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/StartSchedules.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ProcedureJob.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ReducerJob.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ScheduleResult.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Reducers/CancelSchedules.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Reducers/StartSchedules.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/ScheduleResult.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/ProcedureJob.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/ReducerJob.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/ScheduleResult.g.cs diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 248b0449e31..ad794219ec6 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -306,6 +306,67 @@ public static async Task FormattedGeneratedCodeCompiles(string fixtureName) AssertContextOwnership(compilation); } + [Theory] + [InlineData("net8.0")] +#if NET10_0_OR_GREATER + [InlineData("net10.0")] +#endif + public static async Task NamespaceImmediateSchedulesUseExplicitFunctionNames(string framework) + { + var fixture = await Fixture.Compile("server", framework); + var source = """ + global using System; + global using System.IO; + global using System.Collections.Generic; + global using System.Linq; + public static partial class Jobs + { + [SpacetimeDB.Reducer(Name = "reducer_job")] + public static void ReducerTick(SpacetimeDB.ReducerContext ctx, uint payload) { } + [SpacetimeDB.Procedure(Name = "procedure_job")] + public static void ProcedureTick(SpacetimeDB.ProcedureContext ctx, uint payload) { } + } + """; + var input = CSharpCompilation.Create( + "ScheduledLibrary", + [CSharpSyntaxTree.ParseText(source, fixture.ParseOptions)], + fixture.SampleCompilation.References, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) + ); + var driver = CSharpGeneratorDriver.Create( + [new Type().AsSourceGenerator(), new Module().AsSourceGenerator()], + parseOptions: fixture.ParseOptions + ); + driver.RunGeneratorsAndUpdateCompilation(input, out var output, out var diagnostics); + Assert.Empty(diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error)); + Assert.Empty(GetCompilationErrors(output)); + + foreach (var (method, wireName) in new[] + { + ("ReducerTick", "reducer_job"), + ("ProcedureTick", "procedure_job"), + }) + { + var helper = Assert.Single(output.SyntaxTrees + .SelectMany(tree => tree.GetRoot().DescendantNodes()) + .OfType() + .Where(node => node.Identifier.ValueText == "VolatileNonatomicScheduleImmediate" + method)); + var call = Assert.Single(helper.DescendantNodes() + .OfType() + .Where(node => node.Expression.ToString().EndsWith(".VolatileNonatomicScheduleImmediate"))); + var name = call.ArgumentList.Arguments[0].Expression; + if (framework == "net10.0") + { + var resolve = Assert.IsType(name); + Assert.Equal("global::SpacetimeDB.Internal.Module.ResolveName", resolve.Expression.ToString()); + Assert.StartsWith("ScheduledLibrary,", (string)output.GetSemanticModel(resolve.SyntaxTree) + .GetConstantValue(resolve.ArgumentList.Arguments[0].Expression).Value!); + name = resolve.ArgumentList.Arguments[1].Expression; + } + Assert.Equal(wireName, output.GetSemanticModel(name.SyntaxTree).GetConstantValue(name).Value); + } + } + [Fact] public static async Task NamespaceDeclarationsParseAndValidate() { diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#Reducers.DemoProcedure.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#Reducers.DemoProcedure.verified.cs index ce3fd066748..72f24562fe9 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#Reducers.DemoProcedure.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#Reducers.DemoProcedure.verified.cs @@ -11,7 +11,7 @@ public static void VolatileNonatomicScheduleImmediateDemoProcedure() using var writer = new BinaryWriter(stream); SpacetimeDB.Internal.ProcedureExtensions.VolatileNonatomicScheduleImmediate( - nameof(DemoProcedure), + "canonical_procedure", stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#Reducers.DemoReducer.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#Reducers.DemoReducer.verified.cs index 85af7c9566c..52c920a182c 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#Reducers.DemoReducer.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#Reducers.DemoReducer.verified.cs @@ -11,7 +11,7 @@ public static void VolatileNonatomicScheduleImmediateDemoReducer(int value) using var writer = new BinaryWriter(stream); new SpacetimeDB.BSATN.I32().Write(writer, value); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - nameof(DemoReducer), + "canonical_reducer", stream ); } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index c38361c60c3..daf8e89b0e2 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -1644,6 +1644,11 @@ public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerCont public Scope.Extensions GenerateSchedule() { var extensions = new Scope.Extensions(Scope, FullName); + var functionName = string.IsNullOrEmpty(CanonicalName) + ? $"nameof({Identifier})" + : SymbolDisplay.FormatLiteral(CanonicalName!, true); + if (declaringAssembly is not null) + functionName = $"global::SpacetimeDB.Internal.Module.ResolveName({SymbolDisplay.FormatLiteral(declaringAssembly, true)}, {functionName})"; // Mark the API as unstable. We use name `STDB_UNSTABLE` because: // 1. It's a close equivalent of the `unstable` Cargo feature in Rust. @@ -1662,7 +1667,7 @@ public Scope.Extensions GenerateSchedule() "\n", Args.Select(a => $"new {a.Type.ToBSATNString()}().Write(writer, {a.Identifier});") )}} - SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate({{(declaringAssembly is null ? $"nameof({Identifier})" : $"global::SpacetimeDB.Internal.Module.ResolveName({SymbolDisplay.FormatLiteral(declaringAssembly, true)}, nameof({Identifier}))")}}, stream); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate({{functionName}}, stream); } """ ); @@ -1868,6 +1873,11 @@ public static byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedure public Scope.Extensions GenerateSchedule() { var extensions = new Scope.Extensions(Scope, FullName); + var functionName = string.IsNullOrEmpty(CanonicalName) + ? $"nameof({Identifier})" + : SymbolDisplay.FormatLiteral(CanonicalName!, true); + if (declaringAssembly is not null) + functionName = $"global::SpacetimeDB.Internal.Module.ResolveName({SymbolDisplay.FormatLiteral(declaringAssembly, true)}, {functionName})"; // Mark the API as unstable. We use name `STDB_UNSTABLE` because: // 1. It's a close equivalent of the `unstable` Cargo feature in Rust. @@ -1886,7 +1896,7 @@ public Scope.Extensions GenerateSchedule() "\n", Args.Select(a => $"new {a.Type.ToBSATNString()}().Write(writer, {a.Identifier});") )}} - SpacetimeDB.Internal.ProcedureExtensions.VolatileNonatomicScheduleImmediate({{(declaringAssembly is null ? $"nameof({Identifier})" : $"global::SpacetimeDB.Internal.Module.ResolveName({SymbolDisplay.FormatLiteral(declaringAssembly, true)}, nameof({Identifier}))")}}, stream); + SpacetimeDB.Internal.ProcedureExtensions.VolatileNonatomicScheduleImmediate({{functionName}}, stream); } """ ); diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs index 66e316b1f29..58c4f186383 100644 --- a/crates/codegen/src/csharp.rs +++ b/crates/codegen/src/csharp.rs @@ -1343,7 +1343,11 @@ impl Lang for CsharpScope<'_> { let method_name = accessor_name.deref().to_case(Case::Pascal); writeln!(output, "new QueryBuilder().From.{method_name}().ToSql(),"); } - for (path, _, table) in module.all_tables_with_prefix().into_iter().filter(|(path, _, table)| { + let mut child_tables = module.all_tables_with_prefix(); + child_tables.sort_by(|(a_path, _, a), (b_path, _, b)| { + (a_path, &a.accessor_name).cmp(&(b_path, &b.accessor_name)) + }); + for (path, _, table) in child_tables.into_iter().filter(|(path, _, table)| { !path.is_empty() && table.table_access == spacetimedb_lib::db::raw_def::v9::TableAccess::Public }) { writeln!( diff --git a/crates/codegen/tests/codegen.rs b/crates/codegen/tests/codegen.rs index 1207809589a..d5aa82e43da 100644 --- a/crates/codegen/tests/codegen.rs +++ b/crates/codegen/tests/codegen.rs @@ -189,16 +189,10 @@ fn namespace_module() -> ModuleDef { } let mut root = scope(AlgebraicType::Bool); - let mut auth = scope(AlgebraicType::U32); - auth.sections - .push(RawModuleDefV10Section::Submodules(vec![RawSubmoduleV10 { - namespace: "nested".into(), - module: scope(AlgebraicType::I64), - }])); root.sections.push(RawModuleDefV10Section::Submodules(vec![ RawSubmoduleV10 { namespace: "MyAuth".into(), - module: auth, + module: scope(AlgebraicType::U32), }, RawSubmoduleV10 { namespace: "class".into(), @@ -232,6 +226,28 @@ fn csharp_namespaces_compile_and_run() { assert!(auth_reducer.code.contains("\"MyAuth.login\"")); assert!(!auth_reducer.code.contains("MyAuth.MyAuth.")); + let client = files + .iter() + .find(|file| file.filename == "SpacetimeDBClient.g.cs") + .unwrap(); + let child_queries: Vec<_> = client + .code + .lines() + .map(str::trim) + .filter(|line| line.starts_with("new QueryBuilder().From.@")) + .filter(|line| line.ends_with(".Notice().ToSql(),") || line.ends_with(".User().ToSql(),")) + .collect(); + assert_eq!( + child_queries, + [ + "new QueryBuilder().From.@MyAuth.Notice().ToSql(),", + "new QueryBuilder().From.@MyAuth.User().ToSql(),", + "new QueryBuilder().From.@class.Notice().ToSql(),", + "new QueryBuilder().From.@class.User().ToSql(),", + ], + "subscribe-all child tables must have stable namespace/accessor order" + ); + compile_csharp_client(files, include_str!("csharp-namespaces/Program.cs")); } diff --git a/crates/codegen/tests/csharp-namespaces/Program.cs b/crates/codegen/tests/csharp-namespaces/Program.cs index 8629ed8bca6..f04cef38917 100644 --- a/crates/codegen/tests/csharp-namespaces/Program.cs +++ b/crates/codegen/tests/csharp-namespaces/Program.cs @@ -9,7 +9,6 @@ using SpacetimeDB.ClientApi; using Auth = Game.Bindings.MyAuth; using Audit = Game.Bindings.@class; -using Nested = Game.Bindings.MyAuth.nested; internal static class Program { @@ -67,23 +66,20 @@ private static void Check(DbConnection conn) Equal("user", conn.Db.User.RemoteTableName); Equal("MyAuth.user", conn.Db.MyAuth.User.RemoteTableName); Equal("class.user", conn.Db.@class.User.RemoteTableName); - Equal("MyAuth.nested.user", conn.Db.MyAuth.nested.User.RemoteTableName); Equal(conn.Db.MyAuth.User, conn.Db.GetTable("MyAuth.user")!); Equal(conn.Db.@class.User, conn.Db.GetTable("class.user")!); - Equal(conn.Db.MyAuth.nested.User, conn.Db.GetTable("MyAuth.nested.user")!); var query = new QueryBuilder(); Equal("SELECT * FROM \"user\"", query.From.User().ToSql()); Equal("SELECT * FROM \"MyAuth\".\"user\"", query.From.MyAuth.User().ToSql()); Equal("SELECT * FROM \"class\".\"user\"", query.From.@class.User().ToSql()); - Equal("SELECT * FROM \"MyAuth\".\"nested\".\"user\"", query.From.MyAuth.nested.User().ToSql()); var filtered = query.From.MyAuth.User().Where(cols => cols.Value.Eq(7U)).ToSql(); if (!filtered.Contains("\"MyAuth\".\"user\".\"value\"")) throw new Exception(filtered); var join = " FROM \"MyAuth\".\"user\" JOIN \"class\".\"user\" ON \"MyAuth\".\"user\".\"id\" = \"class\".\"user\".\"id\""; Equal("SELECT \"MyAuth\".\"user\".*" + join, query.From.MyAuth.User().LeftSemijoin(query.From.@class.User(), (l, r) => l.Id.Eq(r.Id)).ToSql()); Equal("SELECT \"class\".\"user\".*" + join, query.From.MyAuth.User().RightSemijoin(query.From.@class.User(), (l, r) => l.Id.Eq(r.Id)).ToSql()); var all = QueryBuilder.AllTablesSqlQueries(); - Equal(12, all.Length); + Equal(9, all.Length); Equal(all.Length, all.Distinct().Count()); Equal(false, all.Any(sql => sql.Contains("secret"))); var sqlName = typeof(Auth.RemoteTables.UserHandle).GetProperty("RemoteSqlTableName", BindingFlags.Instance | BindingFlags.NonPublic)!; @@ -92,7 +88,6 @@ private static void Check(DbConnection conn) var root = new User(1, true); var auth = new Auth.User(1, 7); var audit = new Audit.User(1, "audit"); - var nested = new Nested.User(1, -1); int inserts = 0; conn.Db.MyAuth.User.OnInsert += (ctx, row) => { @@ -105,13 +100,11 @@ private static void Check(DbConnection conn) Apply(conn, Change("user", new[] { root }, Array.Empty()), Change("MyAuth.user", new[] { auth }, Array.Empty()), - Change("class.user", new[] { audit }, Array.Empty()), - Change("MyAuth.nested.user", new[] { nested }, Array.Empty())); + Change("class.user", new[] { audit }, Array.Empty())); Equal(1, inserts); Equal(auth, conn.Db.MyAuth.User.Id.Find(1)); Equal(audit, conn.Db.@class.User.Id.Find(1)); Equal("audit", conn.Db.@class.User.Iter().Single().Value); - Equal(-1L, conn.Db.MyAuth.nested.User.Iter().Single().Value); int updates = 0; conn.Db.MyAuth.User.OnUpdate += (ctx, oldRow, newRow) => { @@ -139,7 +132,7 @@ private static void Check(DbConnection conn) Equal("MyAuth.login", ((IReducerArgs)new Auth.Reducer.Login(auth)).ReducerName); Equal("class.login", ((IReducerArgs)new Audit.Reducer.Login(audit)).ReducerName); - Equal("MyAuth.nested.get_user", ((IProcedureArgs)new Nested.Procedure.GetUserArgs()).ProcedureName); + Equal("MyAuth.get_user", ((IProcedureArgs)new Auth.Procedure.GetUserArgs()).ProcedureName); // Function-only types are emitted and remain in their owning typespace. _ = new Auth.Procedure.GetPayload { Value = new Auth.Payload("auth") }; _ = new Audit.Procedure.GetUser { Value = audit }; @@ -147,7 +140,8 @@ private static void Check(DbConnection conn) int authCalls = 0, auditCalls = 0, errors = 0; conn.Reducers.MyAuth.OnLogin += (ctx, row) => { Equal(auth, row); authCalls++; }; - conn.Reducers.@class.OnLogin += (ctx, row) => { Equal(audit, row); auditCalls++; }; + void OnAuditLogin(ReducerEventContext ctx, Audit.User row) { Equal(audit, row); auditCalls++; } + conn.Reducers.@class.OnLogin += OnAuditLogin; conn.OnUnhandledReducerError += (ctx, error) => { Equal("failed", error.Message); errors++; }; var dispatch = typeof(DbConnection).GetMethod("Dispatch", BindingFlags.NonPublic | BindingFlags.Instance)!; void Dispatch(Reducer args, Status status) @@ -157,7 +151,8 @@ void Dispatch(Reducer args, Status status) } Dispatch(new Auth.Reducer.Login(auth), new Status.Committed(new Unit())); Dispatch(new Audit.Reducer.Login(audit), new Status.Committed(new Unit())); - Dispatch(new Nested.Reducer.Login(nested), new Status.Failed("failed")); + conn.Reducers.@class.OnLogin -= OnAuditLogin; + Dispatch(new Audit.Reducer.Login(audit), new Status.Failed("failed")); Equal(1, authCalls); Equal(1, auditCalls); Equal(1, errors); diff --git a/modules/namespace-test-cs/libraries/AuditLib/Scheduled.cs b/modules/namespace-test-cs/libraries/AuditLib/Scheduled.cs new file mode 100644 index 00000000000..a681356f59d --- /dev/null +++ b/modules/namespace-test-cs/libraries/AuditLib/Scheduled.cs @@ -0,0 +1,164 @@ +using SpacetimeDB; + +#pragma warning disable STDB_UNSTABLE + +namespace AuditLib; + +[Table( + Accessor = "ReducerJob", + Name = "reducer_jobs", + Scheduled = nameof(ScheduledFunctions.ReducerTick), + ScheduledAt = nameof(Due) +)] +public partial struct ReducerJob +{ + [PrimaryKey, AutoInc] + public ulong Id; + public uint JobId; + public ScheduleAt Due; + public uint Payload; +} + +[Table( + Accessor = "ProcedureJob", + Name = "procedure_jobs", + Scheduled = nameof(ScheduledFunctions.ProcedureTick), + ScheduledAt = nameof(Due) +)] +public partial struct ProcedureJob +{ + [PrimaryKey, AutoInc] + public ulong Id; + public uint JobId; + public uint Payload; + public ScheduleAt Due; +} + +[Table(Accessor = "ScheduleResult", Public = true)] +public partial struct ScheduleResult +{ + [PrimaryKey] + public uint JobId; + public uint Payload; + public string Kind; + public uint Executions; + public ulong ScheduledId; +} + +public static partial class ScheduledFunctions +{ + private const uint PayloadBase = 2000; + + [Reducer] + public static void StartSchedules(ReducerContext ctx) + { + var due = new ScheduleAt.Time(ctx.Timestamp + new TimeDuration(100_000)); + ctx.Db.ReducerJob.Insert( + new ReducerJob + { + JobId = 1, + Due = due, + Payload = PayloadBase + 1, + } + ); + ctx.Db.ProcedureJob.Insert( + new ProcedureJob + { + JobId = 2, + Due = due, + Payload = PayloadBase + 2, + } + ); + VolatileNonatomicScheduleImmediateReducerTick( + new ReducerJob + { + JobId = 3, + Due = due, + Payload = PayloadBase + 3, + } + ); + VolatileNonatomicScheduleImmediateProcedureTick( + new ProcedureJob + { + JobId = 4, + Due = due, + Payload = PayloadBase + 4, + } + ); + ctx.Db.ReducerJob.Insert( + new ReducerJob + { + JobId = 5, + Due = new ScheduleAt.Interval(new TimeDuration(100_000)), + Payload = PayloadBase + 5, + } + ); + } + + [Reducer(Name = "run_reducer_job")] + public static void ReducerTick(ReducerContext ctx, ReducerJob job) + { + var previous = ctx.Db.ScheduleResult.JobId.Find(job.JobId); + var result = new ScheduleResult + { + JobId = job.JobId, + Payload = job.Payload, + Kind = "reducer", + Executions = (previous?.Executions ?? 0) + 1, + ScheduledId = job.Id, + }; + if (previous is null) + ctx.Db.ScheduleResult.Insert(result); + else + ctx.Db.ScheduleResult.JobId.Update(result); + } + + [Procedure(Name = "run_procedure_job")] + public static void ProcedureTick(ProcedureContext ctx, ProcedureJob job) + { + ctx.WithTx(tx => + { + var previous = tx.Db.ScheduleResult.JobId.Find(job.JobId); + var result = new ScheduleResult + { + JobId = job.JobId, + Payload = job.Payload, + Kind = "procedure", + Executions = (previous?.Executions ?? 0) + 1, + ScheduledId = job.Id, + }; + if (previous is null) + tx.Db.ScheduleResult.Insert(result); + else + tx.Db.ScheduleResult.JobId.Update(result); + return 0; + }); + } + + [Reducer] + public static void CancelSchedules(ReducerContext ctx) + { + var repeat = ctx.Db.ScheduleResult.JobId.Find(5)!.Value; + if (repeat.Executions < 2) + throw new Exception("Repeating schedule has not run twice."); + ctx.Db.ReducerJob.Id.Delete(repeat.ScheduledId); + ctx.Db.ScheduleResult.Insert( + new ScheduleResult + { + JobId = 6, + Payload = PayloadBase + 6, + Kind = "cancel", + Executions = repeat.Executions, + } + ); + // This later job provides a scheduler-driven observation point after cancellation. + ctx.Db.ReducerJob.Insert( + new ReducerJob + { + JobId = 7, + Due = new ScheduleAt.Time(ctx.Timestamp + new TimeDuration(500_000)), + Payload = PayloadBase + 7, + } + ); + } +} diff --git a/modules/namespace-test-cs/libraries/AuthLib/Scheduled.cs b/modules/namespace-test-cs/libraries/AuthLib/Scheduled.cs new file mode 100644 index 00000000000..9778673d889 --- /dev/null +++ b/modules/namespace-test-cs/libraries/AuthLib/Scheduled.cs @@ -0,0 +1,164 @@ +using SpacetimeDB; + +#pragma warning disable STDB_UNSTABLE + +namespace AuthLib; + +[Table( + Accessor = "ReducerJob", + Name = "reducer_jobs", + Scheduled = nameof(ScheduledFunctions.ReducerTick), + ScheduledAt = nameof(Due) +)] +public partial struct ReducerJob +{ + [PrimaryKey, AutoInc] + public ulong Id; + public uint JobId; + public ScheduleAt Due; + public uint Payload; +} + +[Table( + Accessor = "ProcedureJob", + Name = "procedure_jobs", + Scheduled = nameof(ScheduledFunctions.ProcedureTick), + ScheduledAt = nameof(Due) +)] +public partial struct ProcedureJob +{ + [PrimaryKey, AutoInc] + public ulong Id; + public uint JobId; + public uint Payload; + public ScheduleAt Due; +} + +[Table(Accessor = "ScheduleResult", Public = true)] +public partial struct ScheduleResult +{ + [PrimaryKey] + public uint JobId; + public uint Payload; + public string Kind; + public uint Executions; + public ulong ScheduledId; +} + +public static partial class ScheduledFunctions +{ + private const uint PayloadBase = 1000; + + [Reducer] + public static void StartSchedules(ReducerContext ctx) + { + var due = new ScheduleAt.Time(ctx.Timestamp + new TimeDuration(100_000)); + ctx.Db.ReducerJob.Insert( + new ReducerJob + { + JobId = 1, + Due = due, + Payload = PayloadBase + 1, + } + ); + ctx.Db.ProcedureJob.Insert( + new ProcedureJob + { + JobId = 2, + Due = due, + Payload = PayloadBase + 2, + } + ); + VolatileNonatomicScheduleImmediateReducerTick( + new ReducerJob + { + JobId = 3, + Due = due, + Payload = PayloadBase + 3, + } + ); + VolatileNonatomicScheduleImmediateProcedureTick( + new ProcedureJob + { + JobId = 4, + Due = due, + Payload = PayloadBase + 4, + } + ); + ctx.Db.ReducerJob.Insert( + new ReducerJob + { + JobId = 5, + Due = new ScheduleAt.Interval(new TimeDuration(100_000)), + Payload = PayloadBase + 5, + } + ); + } + + [Reducer(Name = "run_reducer_job")] + public static void ReducerTick(ReducerContext ctx, ReducerJob job) + { + var previous = ctx.Db.ScheduleResult.JobId.Find(job.JobId); + var result = new ScheduleResult + { + JobId = job.JobId, + Payload = job.Payload, + Kind = "reducer", + Executions = (previous?.Executions ?? 0) + 1, + ScheduledId = job.Id, + }; + if (previous is null) + ctx.Db.ScheduleResult.Insert(result); + else + ctx.Db.ScheduleResult.JobId.Update(result); + } + + [Procedure(Name = "run_procedure_job")] + public static void ProcedureTick(ProcedureContext ctx, ProcedureJob job) + { + ctx.WithTx(tx => + { + var previous = tx.Db.ScheduleResult.JobId.Find(job.JobId); + var result = new ScheduleResult + { + JobId = job.JobId, + Payload = job.Payload, + Kind = "procedure", + Executions = (previous?.Executions ?? 0) + 1, + ScheduledId = job.Id, + }; + if (previous is null) + tx.Db.ScheduleResult.Insert(result); + else + tx.Db.ScheduleResult.JobId.Update(result); + return 0; + }); + } + + [Reducer] + public static void CancelSchedules(ReducerContext ctx) + { + var repeat = ctx.Db.ScheduleResult.JobId.Find(5)!.Value; + if (repeat.Executions < 2) + throw new Exception("Repeating schedule has not run twice."); + ctx.Db.ReducerJob.Id.Delete(repeat.ScheduledId); + ctx.Db.ScheduleResult.Insert( + new ScheduleResult + { + JobId = 6, + Payload = PayloadBase + 6, + Kind = "cancel", + Executions = repeat.Executions, + } + ); + // This later job provides a scheduler-driven observation point after cancellation. + ctx.Db.ReducerJob.Insert( + new ReducerJob + { + JobId = 7, + Due = new ScheduleAt.Time(ctx.Timestamp + new TimeDuration(500_000)), + Payload = PayloadBase + 7, + } + ); + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs index 124748d95ee..32e44831c16 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs @@ -61,6 +61,8 @@ void EmptyCache() conn.Db.User.Count == 0 && conn.Db.MyAuth.User.Count == 0 && conn.Db.@class.User.Count == 0 + && conn.Db.MyAuth.ScheduleResult.Count == 0 + && conn.Db.@class.ScheduleResult.Count == 0 && conn.Db.ExtraRow.Count == 0, "Unsubscribe must clear every namespace's table cache" ); @@ -111,7 +113,10 @@ void EmptyCache() EmptyCache(); conn.Reducers.Extra(); - Wait(() => conn.Db.ExtraRow.Count == 1, "dependency automatically registered in public"); + Wait( + () => conn.Db.ExtraRow.Count == 1, + "dependency automatically registered in public" + ); var exerciseDone = false; var atomicInsert = false; conn.Db.User.OnInsert += (ctx, row) => @@ -338,6 +343,115 @@ void EmptyCache() "Subscribe-all omitted child tables or views" ); Require(notices == 1, "Event rows must not be replayed as persistent rows"); + + foreach (var reducers in new object[] { conn.Reducers.MyAuth, conn.Reducers.@class }) + { + Require( + reducers.GetType().GetMethod("ReducerTick") == null + && reducers.GetType().GetMethod("RunReducerJob") == null, + "Scheduled reducers must not have client call methods" + ); + } + foreach ( + var procedureCalls in new object[] + { + conn.Procedures.MyAuth, + conn.Procedures.@class, + } + ) + { + Require( + procedureCalls.GetType().GetMethod("ProcedureTick") == null + && procedureCalls.GetType().GetMethod("RunProcedureJob") == null, + "Scheduled procedures must not have client call methods" + ); + } + + conn.Reducers.MyAuth.StartSchedules(); + Wait( + () => + conn.Db.MyAuth.ScheduleResult.Count == 5 + && conn.Db.MyAuth.ScheduleResult.JobId.Find(5)?.Executions >= 2, + "Auth one-shot, immediate, and repeating schedules" + ); + Require( + conn.Db.@class.ScheduleResult.Count == 0, + "Auth schedules must not execute Audit functions or write Audit tables" + ); + conn.Reducers.@class.StartSchedules(); + Wait( + () => + conn.Db.@class.ScheduleResult.Count == 5 + && conn.Db.@class.ScheduleResult.JobId.Find(5)?.Executions >= 2, + "Audit one-shot, immediate, and repeating schedules" + ); + conn.Reducers.MyAuth.CancelSchedules(); + conn.Reducers.@class.CancelSchedules(); + Wait( + () => + conn.Db.MyAuth.ScheduleResult.JobId.Find(7) != null + && conn.Db.@class.ScheduleResult.JobId.Find(7) != null, + "Post-cancellation scheduled jobs" + ); + + void CheckSchedules( + (uint JobId, uint Payload, string Kind, uint Executions, ulong ScheduledId)[] rows, + uint payloadBase + ) + { + Require( + rows.Length == 7, + "Each namespace must have exactly seven schedule results" + ); + foreach (var row in rows) + { + Require(row.Payload == payloadBase + row.JobId, "Scheduled argument payload"); + var kind = + row.JobId == 6 ? "cancel" + : row.JobId == 2 || row.JobId == 4 ? "procedure" + : "reducer"; + Require(row.Kind == kind, "Scheduled function dispatch category"); + Require( + row.JobId == 5 || row.JobId == 6 + ? row.Executions >= 2 + : row.Executions == 1, + "One-shot jobs must run once; repeating jobs must run at least twice" + ); + Require( + row.JobId == 3 || row.JobId == 4 || row.JobId == 6 + ? row.ScheduledId == 0 + : row.ScheduledId > 0, + "Table-backed schedules must receive their generated primary key" + ); + } + Require( + rows.Single(row => row.JobId == 5).Executions + == rows.Single(row => row.JobId == 6).Executions, + "Deleting a repeating schedule must stop further executions" + ); + } + CheckSchedules( + conn.Db.MyAuth.ScheduleResult.Iter() + .Select(row => + (row.JobId, row.Payload, row.Kind, row.Executions, row.ScheduledId) + ) + .ToArray(), + 1000 + ); + CheckSchedules( + conn.Db.@class.ScheduleResult.Iter() + .Select(row => + (row.JobId, row.Payload, row.Kind, row.Executions, row.ScheduledId) + ) + .ToArray(), + 2000 + ); + Require( + conn.Db.User.Count == 1 + && conn.Db.MyAuth.User.Count == 1 + && conn.Db.@class.User.Count == 2, + "Schedules must leave unrelated tables unchanged" + ); Unsubscribe(all); EmptyCache(); Console.WriteLine("Namespace integration passed"); diff --git a/sdks/csharp/examples~/regression-tests/namespaces/README.md b/sdks/csharp/examples~/regression-tests/namespaces/README.md index 36edcfabff9..e5380e9eb92 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/README.md +++ b/sdks/csharp/examples~/regression-tests/namespaces/README.md @@ -35,6 +35,10 @@ Coverage: - Event rows, private-table access rejection, procedural/anonymous/query views. - `RemoteQuery` result decoding and no subscription-cache population by one-off queries. - Subscribe-all initial rows, no replay of past events, and unsubscribe cache cleanup. +- Same-named scheduled reducers/procedures in both namespaces, with explicit function + and table names and custom scheduled-at columns. Covers one-shot and immediate + execution, repeating reducer cancellation, argument payloads, generated keys, + namespace isolation, and absence of scheduled functions from client call APIs. Assertions throw in both Debug and Release. Every asynchronous phase has a timeout. The generated bindings are committed and regenerated through the normal CLI path. diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs index db83438308f..a4f5e918e69 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs @@ -26,6 +26,7 @@ internal RemoteTables(global::SpacetimeDB.Types.DbConnection conn, Action AnonymousUsers() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users"), new AnonymousUsersCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users")), new AnonymousUsersIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users"))); public global::SpacetimeDB.Table Notice() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice"), new NoticeCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice")), new NoticeIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice"))); public global::SpacetimeDB.Table QueryUsers() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users"), new QueryUsersCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users")), new QueryUsersIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users"))); + public global::SpacetimeDB.Table ScheduleResult() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "schedule_result"), new ScheduleResultCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "schedule_result")), new ScheduleResultIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "schedule_result"))); public global::SpacetimeDB.Table User() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users"), new UserCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users")), new UserIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users"))); public global::SpacetimeDB.Table Users() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "users"), new UsersCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "users")), new UsersIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "users"))); } diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/CancelSchedules.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/CancelSchedules.g.cs new file mode 100644 index 00000000000..93ac858ad16 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/CancelSchedules.g.cs @@ -0,0 +1,53 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void CancelSchedulesHandler(global::SpacetimeDB.Types.ReducerEventContext ctx); + public event CancelSchedulesHandler? OnCancelSchedules; + + public void CancelSchedules() + { + conn.InternalCallReducer(new Reducer.CancelSchedules()); + } + + public bool InvokeCancelSchedules(global::SpacetimeDB.Types.ReducerEventContext ctx, Reducer.CancelSchedules args) + { + if (OnCancelSchedules == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnCancelSchedules( + ctx + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class CancelSchedules : global::SpacetimeDB.Types.Reducer, IReducerArgs + { + string IReducerArgs.ReducerName => "MyAuth.cancel_schedules"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/StartSchedules.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/StartSchedules.g.cs new file mode 100644 index 00000000000..6735514356e --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/StartSchedules.g.cs @@ -0,0 +1,53 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void StartSchedulesHandler(global::SpacetimeDB.Types.ReducerEventContext ctx); + public event StartSchedulesHandler? OnStartSchedules; + + public void StartSchedules() + { + conn.InternalCallReducer(new Reducer.StartSchedules()); + } + + public bool InvokeStartSchedules(global::SpacetimeDB.Types.ReducerEventContext ctx, Reducer.StartSchedules args) + { + if (OnStartSchedules == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnStartSchedules( + ctx + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class StartSchedules : global::SpacetimeDB.Types.Reducer, IReducerArgs + { + string IReducerArgs.ReducerName => "MyAuth.start_schedules"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs new file mode 100644 index 00000000000..8bc0c3379d9 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs @@ -0,0 +1,68 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteTables + { + public sealed class ScheduleResultHandle : RemoteTableHandle + { + public override string RemoteTableName => "MyAuth.schedule_result"; + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "schedule_result"); + + public sealed class JobIdUniqueIndex : UniqueIndexBase + { + protected override uint GetKey(ScheduleResult row) => row.JobId; + + public JobIdUniqueIndex(ScheduleResultHandle table) : base(table) { } + } + + public readonly JobIdUniqueIndex JobId; + + internal ScheduleResultHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) + { + JobId = new(this); + } + + protected override object GetPrimaryKey(ScheduleResult row) => row.JobId; + } + + public readonly ScheduleResultHandle ScheduleResult; + } + + public sealed class ScheduleResultCols + { + public global::SpacetimeDB.Col JobId { get; } + public global::SpacetimeDB.Col Payload { get; } + public global::SpacetimeDB.Col Kind { get; } + public global::SpacetimeDB.Col Executions { get; } + public global::SpacetimeDB.Col ScheduledId { get; } + + public ScheduleResultCols(global::SpacetimeDB.SqlTableName tableName) + { + JobId = new global::SpacetimeDB.Col(tableName, "job_id"); + Payload = new global::SpacetimeDB.Col(tableName, "payload"); + Kind = new global::SpacetimeDB.Col(tableName, "kind"); + Executions = new global::SpacetimeDB.Col(tableName, "executions"); + ScheduledId = new global::SpacetimeDB.Col(tableName, "scheduled_id"); + } + } + + public sealed class ScheduleResultIxCols + { + public global::SpacetimeDB.IxCol JobId { get; } + + public ScheduleResultIxCols(global::SpacetimeDB.SqlTableName tableName) + { + JobId = new global::SpacetimeDB.IxCol(tableName, "job_id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ProcedureJob.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ProcedureJob.g.cs new file mode 100644 index 00000000000..77cf6187ad6 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ProcedureJob.g.cs @@ -0,0 +1,43 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ProcedureJob + { + [DataMember(Name = "id")] + public ulong Id; + [DataMember(Name = "job_id")] + public uint JobId; + [DataMember(Name = "payload")] + public uint Payload; + [DataMember(Name = "due")] + public SpacetimeDB.ScheduleAt Due; + + public ProcedureJob( + ulong Id, + uint JobId, + uint Payload, + SpacetimeDB.ScheduleAt Due + ) + { + this.Id = Id; + this.JobId = JobId; + this.Payload = Payload; + this.Due = Due; + } + + public ProcedureJob() + { + this.Due = null!; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ReducerJob.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ReducerJob.g.cs new file mode 100644 index 00000000000..8494c957ef8 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ReducerJob.g.cs @@ -0,0 +1,43 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ReducerJob + { + [DataMember(Name = "id")] + public ulong Id; + [DataMember(Name = "job_id")] + public uint JobId; + [DataMember(Name = "due")] + public SpacetimeDB.ScheduleAt Due; + [DataMember(Name = "payload")] + public uint Payload; + + public ReducerJob( + ulong Id, + uint JobId, + SpacetimeDB.ScheduleAt Due, + uint Payload + ) + { + this.Id = Id; + this.JobId = JobId; + this.Due = Due; + this.Payload = Payload; + } + + public ReducerJob() + { + this.Due = null!; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ScheduleResult.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ScheduleResult.g.cs new file mode 100644 index 00000000000..32cff37367d --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ScheduleResult.g.cs @@ -0,0 +1,47 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ScheduleResult + { + [DataMember(Name = "job_id")] + public uint JobId; + [DataMember(Name = "payload")] + public uint Payload; + [DataMember(Name = "kind")] + public string Kind; + [DataMember(Name = "executions")] + public uint Executions; + [DataMember(Name = "scheduled_id")] + public ulong ScheduledId; + + public ScheduleResult( + uint JobId, + uint Payload, + string Kind, + uint Executions, + ulong ScheduledId + ) + { + this.JobId = JobId; + this.Payload = Payload; + this.Kind = Kind; + this.Executions = Executions; + this.ScheduledId = ScheduledId; + } + + public ScheduleResult() + { + this.Kind = ""; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs index 02ffeaa503c..db6f7818c48 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.10.1 (commit bc86b7fc7cf3f6a7408e64cf13cab594c20afbc2). +// This was generated using spacetimedb cli version 2.10.1 (commit 6fff5d1a2fd5375aada3d04ab99ae3352229b7d6). #nullable enable @@ -557,9 +557,11 @@ public sealed class QueryBuilder new QueryBuilder().From.QueryUsersRight().ToSql(), new QueryBuilder().From.User().ToSql(), new QueryBuilder().From.Users().ToSql(), - new QueryBuilder().From.@class.User().ToSql(), new QueryBuilder().From.@MyAuth.Notice().ToSql(), + new QueryBuilder().From.@MyAuth.ScheduleResult().ToSql(), new QueryBuilder().From.@MyAuth.User().ToSql(), + new QueryBuilder().From.@class.ScheduleResult().ToSql(), + new QueryBuilder().From.@class.User().ToSql(), new QueryBuilder().From.@MyAuth.QueryUsers().ToSql(), new QueryBuilder().From.@MyAuth.Users().ToSql(), new QueryBuilder().From.@MyAuth.AnonymousUsers().ToSql(), @@ -663,9 +665,13 @@ protected override bool Dispatch(IReducerEventContext context, Reducer reducer) Reducer.Exercise args => Reducers.InvokeExercise(eventContext, args), Reducer.Extra args => Reducers.InvokeExtra(eventContext, args), global::SpacetimeDB.Types.@class.Reducer.Add args => Reducers.@class.InvokeAdd(eventContext, args), + global::SpacetimeDB.Types.@class.Reducer.CancelSchedules args => Reducers.@class.InvokeCancelSchedules(eventContext, args), + global::SpacetimeDB.Types.@class.Reducer.StartSchedules args => Reducers.@class.InvokeStartSchedules(eventContext, args), global::SpacetimeDB.Types.@MyAuth.Reducer.Add args => Reducers.@MyAuth.InvokeAdd(eventContext, args), + global::SpacetimeDB.Types.@MyAuth.Reducer.CancelSchedules args => Reducers.@MyAuth.InvokeCancelSchedules(eventContext, args), global::SpacetimeDB.Types.@MyAuth.Reducer.Fail args => Reducers.@MyAuth.InvokeFail(eventContext, args), global::SpacetimeDB.Types.@MyAuth.Reducer.Remove args => Reducers.@MyAuth.InvokeRemove(eventContext, args), + global::SpacetimeDB.Types.@MyAuth.Reducer.StartSchedules args => Reducers.@MyAuth.InvokeStartSchedules(eventContext, args), global::SpacetimeDB.Types.@MyAuth.Reducer.Update args => Reducers.@MyAuth.InvokeUpdate(eventContext, args), _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Namespace.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Namespace.g.cs index 8d9731616d7..5a16f7f33ed 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Namespace.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Namespace.g.cs @@ -23,11 +23,13 @@ public sealed partial class RemoteTables { internal RemoteTables(global::SpacetimeDB.Types.DbConnection conn, Action register) { + register(ScheduleResult = new(conn)); register(User = new(conn)); } } public sealed class From { + public global::SpacetimeDB.Table ScheduleResult() => new(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "schedule_result"), new ScheduleResultCols(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "schedule_result")), new ScheduleResultIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "schedule_result"))); public global::SpacetimeDB.Table User() => new(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "user"), new UserCols(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "user")), new UserIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "user"))); } diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Reducers/CancelSchedules.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Reducers/CancelSchedules.g.cs new file mode 100644 index 00000000000..bf8783d6429 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Reducers/CancelSchedules.g.cs @@ -0,0 +1,53 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@class +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void CancelSchedulesHandler(global::SpacetimeDB.Types.ReducerEventContext ctx); + public event CancelSchedulesHandler? OnCancelSchedules; + + public void CancelSchedules() + { + conn.InternalCallReducer(new Reducer.CancelSchedules()); + } + + public bool InvokeCancelSchedules(global::SpacetimeDB.Types.ReducerEventContext ctx, Reducer.CancelSchedules args) + { + if (OnCancelSchedules == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnCancelSchedules( + ctx + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class CancelSchedules : global::SpacetimeDB.Types.Reducer, IReducerArgs + { + string IReducerArgs.ReducerName => "class.cancel_schedules"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Reducers/StartSchedules.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Reducers/StartSchedules.g.cs new file mode 100644 index 00000000000..cb9eeddaad2 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Reducers/StartSchedules.g.cs @@ -0,0 +1,53 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@class +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void StartSchedulesHandler(global::SpacetimeDB.Types.ReducerEventContext ctx); + public event StartSchedulesHandler? OnStartSchedules; + + public void StartSchedules() + { + conn.InternalCallReducer(new Reducer.StartSchedules()); + } + + public bool InvokeStartSchedules(global::SpacetimeDB.Types.ReducerEventContext ctx, Reducer.StartSchedules args) + { + if (OnStartSchedules == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnStartSchedules( + ctx + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class StartSchedules : global::SpacetimeDB.Types.Reducer, IReducerArgs + { + string IReducerArgs.ReducerName => "class.start_schedules"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/ScheduleResult.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/ScheduleResult.g.cs new file mode 100644 index 00000000000..44a53746ffa --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/ScheduleResult.g.cs @@ -0,0 +1,68 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@class +{ + public sealed partial class RemoteTables + { + public sealed class ScheduleResultHandle : RemoteTableHandle + { + public override string RemoteTableName => "class.schedule_result"; + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "schedule_result"); + + public sealed class JobIdUniqueIndex : UniqueIndexBase + { + protected override uint GetKey(ScheduleResult row) => row.JobId; + + public JobIdUniqueIndex(ScheduleResultHandle table) : base(table) { } + } + + public readonly JobIdUniqueIndex JobId; + + internal ScheduleResultHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) + { + JobId = new(this); + } + + protected override object GetPrimaryKey(ScheduleResult row) => row.JobId; + } + + public readonly ScheduleResultHandle ScheduleResult; + } + + public sealed class ScheduleResultCols + { + public global::SpacetimeDB.Col JobId { get; } + public global::SpacetimeDB.Col Payload { get; } + public global::SpacetimeDB.Col Kind { get; } + public global::SpacetimeDB.Col Executions { get; } + public global::SpacetimeDB.Col ScheduledId { get; } + + public ScheduleResultCols(global::SpacetimeDB.SqlTableName tableName) + { + JobId = new global::SpacetimeDB.Col(tableName, "job_id"); + Payload = new global::SpacetimeDB.Col(tableName, "payload"); + Kind = new global::SpacetimeDB.Col(tableName, "kind"); + Executions = new global::SpacetimeDB.Col(tableName, "executions"); + ScheduledId = new global::SpacetimeDB.Col(tableName, "scheduled_id"); + } + } + + public sealed class ScheduleResultIxCols + { + public global::SpacetimeDB.IxCol JobId { get; } + + public ScheduleResultIxCols(global::SpacetimeDB.SqlTableName tableName) + { + JobId = new global::SpacetimeDB.IxCol(tableName, "job_id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/ProcedureJob.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/ProcedureJob.g.cs new file mode 100644 index 00000000000..d3fd05377ae --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/ProcedureJob.g.cs @@ -0,0 +1,43 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@class +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ProcedureJob + { + [DataMember(Name = "id")] + public ulong Id; + [DataMember(Name = "job_id")] + public uint JobId; + [DataMember(Name = "payload")] + public uint Payload; + [DataMember(Name = "due")] + public SpacetimeDB.ScheduleAt Due; + + public ProcedureJob( + ulong Id, + uint JobId, + uint Payload, + SpacetimeDB.ScheduleAt Due + ) + { + this.Id = Id; + this.JobId = JobId; + this.Payload = Payload; + this.Due = Due; + } + + public ProcedureJob() + { + this.Due = null!; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/ReducerJob.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/ReducerJob.g.cs new file mode 100644 index 00000000000..330424cf635 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/ReducerJob.g.cs @@ -0,0 +1,43 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@class +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ReducerJob + { + [DataMember(Name = "id")] + public ulong Id; + [DataMember(Name = "job_id")] + public uint JobId; + [DataMember(Name = "due")] + public SpacetimeDB.ScheduleAt Due; + [DataMember(Name = "payload")] + public uint Payload; + + public ReducerJob( + ulong Id, + uint JobId, + SpacetimeDB.ScheduleAt Due, + uint Payload + ) + { + this.Id = Id; + this.JobId = JobId; + this.Due = Due; + this.Payload = Payload; + } + + public ReducerJob() + { + this.Due = null!; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/ScheduleResult.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/ScheduleResult.g.cs new file mode 100644 index 00000000000..5994827df3c --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Types/ScheduleResult.g.cs @@ -0,0 +1,47 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@class +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ScheduleResult + { + [DataMember(Name = "job_id")] + public uint JobId; + [DataMember(Name = "payload")] + public uint Payload; + [DataMember(Name = "kind")] + public string Kind; + [DataMember(Name = "executions")] + public uint Executions; + [DataMember(Name = "scheduled_id")] + public ulong ScheduledId; + + public ScheduleResult( + uint JobId, + uint Payload, + string Kind, + uint Executions, + ulong ScheduledId + ) + { + this.JobId = JobId; + this.Payload = Payload; + this.Kind = Kind; + this.Executions = Executions; + this.ScheduledId = ScheduledId; + } + + public ScheduleResult() + { + this.Kind = ""; + } + } +} From cf7e23a892770b48328b669a690d236a39290e5c Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Fri, 18 Sep 2026 08:20:16 -0500 Subject: [PATCH 13/49] Procedure transaction writing across root and namespace tables --- modules/namespace-test-cs/Lib.cs | 12 +++ .../libraries/AuthLib/Lib.cs | 3 + .../regression-tests/namespaces/Program.cs | 74 +++++++++++++++++ .../regression-tests/namespaces/README.md | 3 + .../Procedures/WriteAcrossNamespaces.g.cs | 82 +++++++++++++++++++ .../module_bindings/SpacetimeDBClient.g.cs | 2 +- 6 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/WriteAcrossNamespaces.g.cs diff --git a/modules/namespace-test-cs/Lib.cs b/modules/namespace-test-cs/Lib.cs index 555eb6b8f95..f82b9df6ad5 100644 --- a/modules/namespace-test-cs/Lib.cs +++ b/modules/namespace-test-cs/Lib.cs @@ -48,6 +48,18 @@ public static void Exercise(ReducerContext ctx) public static ulong CountUsers(ProcedureContext ctx) => ctx.WithTx(tx => tx.Db.User.Count + tx.Db.MyAuth.User.Count + tx.Db.@class.User.Count); + [Procedure] + public static uint WriteAcrossNamespaces(ProcedureContext ctx, uint id, bool fail) => + ctx.WithTx(tx => + { + tx.Db.User.Insert(new User { Id = id }); + AuthLib.Functions.Insert(tx, id); + tx.Db.@class.User.Insert(new AuditLib.User { Id = id, Message = "procedure" }); + if (fail) + throw new Exception("cross-namespace procedure rollback"); + return tx.Db.MyAuth.User.Id.Find(id)!.Value.Score; + }); + [View(Accessor = "Users", Public = true)] public static User? Users(ViewContext ctx) => ctx.Db.User.Id.Find(2); diff --git a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs index 79e7c37db18..470c08a0133 100644 --- a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs +++ b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs @@ -32,6 +32,9 @@ public static partial class Functions public static void Insert(ReducerContext ctx, uint id) => ctx.Db.User.Insert(new User { Id = id, Score = 42 }); + public static void Insert(ProcedureTxContext ctx, uint id) => + ctx.Db.User.Insert(new User { Id = id, Score = 42 }); + public static ulong Count(ReducerContext ctx) => ctx.Db.User.Count; public static FromWhere Query(ViewContext ctx) => diff --git a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs index 32e44831c16..69e507dece5 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs @@ -452,6 +452,80 @@ uint payloadBase && conn.Db.@class.User.Count == 2, "Schedules must leave unrelated tables unchanged" ); + + var transactionInserts = 0; + void CheckTransactionInsert(EventContext ctx, uint id) + { + if (id < 20) + return; + Require(id == 20, "A rolled-back procedure emitted an insert"); + Require( + ctx.Db.User.Id.Find(id) != null + && ctx.Db.MyAuth.User.Id.Find(id)?.Score == 42 + && ctx.Db.@class.User.Id.Find(id)?.Message == "procedure", + "Every insert callback must see the whole procedure transaction" + ); + transactionInserts++; + } + conn.Db.User.OnInsert += (ctx, row) => CheckTransactionInsert(ctx, row.Id); + conn.Db.MyAuth.User.OnInsert += (ctx, row) => CheckTransactionInsert(ctx, row.Id); + conn.Db.@class.User.OnInsert += (ctx, row) => CheckTransactionInsert(ctx, row.Id); + + var transactionCommitted = false; + conn.Procedures.WriteAcrossNamespaces( + 20, + false, + (_, result) => + { + Require(result.IsSuccess && result.Value == 42, "Procedure transaction commit"); + transactionCommitted = true; + } + ); + Wait( + () => transactionCommitted && transactionInserts == 3, + "Committed cross-namespace procedure transaction" + ); + var transactionFailed = false; + conn.Procedures.WriteAcrossNamespaces( + 21, + true, + (_, result) => + { + Require( + !result.IsSuccess && result.Error != null, + "Procedure transaction must report failure" + ); + transactionFailed = true; + } + ); + Wait(() => transactionFailed, "Failed cross-namespace procedure transaction"); + + // Query the host as well as the cache: no subscription update alone does not prove rollback. + var rootWrites = conn.Db.User.RemoteQuery("WHERE id >= 20"); + var authWrites = conn.Db.MyAuth.User.RemoteQuery("WHERE id >= 20"); + var auditWrites = conn.Db.@class.User.RemoteQuery("WHERE id >= 20"); + Wait( + () => rootWrites.IsCompleted && authWrites.IsCompleted && auditWrites.IsCompleted, + "Procedure transaction persistence" + ); + Require(rootWrites.GetAwaiter().GetResult().Single().Id == 20, "Root write rollback"); + var authWrite = authWrites.GetAwaiter().GetResult().Single(); + var auditWrite = auditWrites.GetAwaiter().GetResult().Single(); + Require(authWrite.Id == 20 && authWrite.Score == 42, "Auth write rollback"); + Require( + auditWrite.Id == 20 && auditWrite.Message == "procedure", + "Audit write rollback" + ); + Require( + transactionInserts == 3 + && conn.Db.User.Count == 2 + && conn.Db.MyAuth.User.Count == 2 + && conn.Db.@class.User.Count == 3 + && conn.Db.User.Id.Find(21) == null + && conn.Db.MyAuth.User.Id.Find(21) == null + && conn.Db.@class.User.Id.Find(21) == null, + "Failed procedure must leave all three subscription caches unchanged" + ); Unsubscribe(all); EmptyCache(); Console.WriteLine("Namespace integration passed"); diff --git a/sdks/csharp/examples~/regression-tests/namespaces/README.md b/sdks/csharp/examples~/regression-tests/namespaces/README.md index e5380e9eb92..1ef7c06d6b8 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/README.md +++ b/sdks/csharp/examples~/regression-tests/namespaces/README.md @@ -29,6 +29,9 @@ Coverage: - Typed subscriptions, filtered queries, both semijoin directions, and overlapping subscriptions without duplicate rows or premature cache removal. - Cross-library helper writes and callbacks observing the complete transaction. +- A procedure transaction writing root and both namespace tables, including a + library-local transaction helper. Checks commit, rollback after an exception, + atomic subscription callbacks, and persisted results through one-off queries. - Same-named reducers/procedures in different namespaces, procedure success/error callbacks, and child reducer failures forwarded to the root connection. - Insert/update/delete callbacks, unique/B-tree indexes, and reducer rollback. diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/WriteAcrossNamespaces.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/WriteAcrossNamespaces.g.cs new file mode 100644 index 00000000000..f955154cb22 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/WriteAcrossNamespaces.g.cs @@ -0,0 +1,82 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteProcedures : RemoteBase + { + public void WriteAcrossNamespaces(uint id, bool fail, ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalWriteAcrossNamespaces(id, fail, (ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalWriteAcrossNamespaces(uint id, bool fail, ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.WriteAcrossNamespacesArgs(id, fail), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class WriteAcrossNamespaces + { + [DataMember(Name = "Value")] + public uint Value; + + public WriteAcrossNamespaces(uint Value) + { + this.Value = Value; + } + + public WriteAcrossNamespaces() + { + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class WriteAcrossNamespacesArgs : Procedure, IProcedureArgs + { + [DataMember(Name = "id")] + public uint Id; + [DataMember(Name = "fail")] + public bool Fail; + + public WriteAcrossNamespacesArgs( + uint Id, + bool Fail + ) + { + this.Id = Id; + this.Fail = Fail; + } + + public WriteAcrossNamespacesArgs() + { + } + + string IProcedureArgs.ProcedureName => "write_across_namespaces"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs index db6f7818c48..2e605f8ef57 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.10.1 (commit 6fff5d1a2fd5375aada3d04ab99ae3352229b7d6). +// This was generated using spacetimedb cli version 2.10.1 (commit 27792e4855011d77014872795ead58a9b0c894e8). #nullable enable From 8a44580b786bf72c0f7975d7c3efec3af44bcb77 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Fri, 18 Sep 2026 09:29:20 -0500 Subject: [PATCH 14/49] Verify --- .../bindings-csharp/Codegen.Tests/TestInit.cs | 2 +- .../snapshots/Type#CustomClass.verified.cs | 2 +- .../snapshots/Type#CustomStruct.verified.cs | 2 +- .../Type#CustomTaggedEnum.verified.cs | 9 +- .../snapshots/Type#PublicTable.verified.cs | 2 +- .../ExtraCompilationErrors.net10.verified.txt | 738 ++ .../ExtraCompilationErrors.verified.txt | 84 +- .../diag/snapshots/Module#FFI.verified.cs | 1936 ++++- .../diag/snapshots/Module#Player.verified.cs | 2 +- .../Module#TestAutoIncNotInteger.verified.cs | 2 +- .../Module#TestDefaultFieldValues.verified.cs | 2 +- .../Module#TestIndexIssues.verified.cs | 2 +- .../Module#TestScheduleIssues.verified.cs | 2 +- .../Module#TestTableTaggedEnum.verified.cs | 9 +- .../Module#TestUniqueNotEquatable.verified.cs | 2 +- .../snapshots/Module.net10#FFI.verified.cs | 6316 +++++++++++++++++ ...mespace.TestDuplicateTableName.verified.cs | 104 + .../snapshots/Module.net10#Player.verified.cs | 101 + ...space.TestDuplicateReducerName.verified.cs | 24 + ...rs.OnReducerWithReservedPrefix.verified.cs | 21 + ...cers.TestDuplicateReducerKind1.verified.cs | 21 + ...cers.TestDuplicateReducerKind2.verified.cs | 21 + ...ucers.TestDuplicateReducerName.verified.cs | 21 + ...Reducers.TestReducerReturnType.verified.cs | 21 + ...cers.TestReducerWithoutContext.verified.cs | 21 + ...rs.__ReducerWithReservedPrefix.verified.cs | 21 + ...le.net10#TestAutoIncNotInteger.verified.cs | 114 + ...e.net10#TestDefaultFieldValues.verified.cs | 242 + ...e.net10#TestDuplicateTableName.verified.cs | 91 + .../Module.net10#TestIndexIssues.verified.cs | 116 + ...leIssues.DummyScheduledReducer.verified.cs | 23 + ...odule.net10#TestScheduleIssues.verified.cs | 142 + ...dule.net10#TestTableTaggedEnum.verified.cs | 83 + ...e.net10#TestUniqueNotEquatable.verified.cs | 115 + .../diag/snapshots/Module.net10.verified.txt | 629 ++ .../diag/snapshots/Type#MyStruct.verified.cs | 2 +- ...ype#NonEquatableViewPrimaryKey.verified.cs | 2 +- ...#NonEquatableViewPrimaryKeyRow.verified.cs | 2 +- .../Type#TestTaggedEnumField.verified.cs | 9 +- ...Type#TestTaggedEnumInlineTuple.verified.cs | 9 +- .../Type#TestTypeParams_T_.verified.cs | 2 +- .../Type#TestUnsupportedType.verified.cs | 2 +- .../Type#ViewPrimaryKeyPartialRow.verified.cs | 2 +- .../Type#ViewPrimaryKeyRenamedRow.verified.cs | 2 +- .../snapshots/Module#DemoTable.verified.cs | 2 +- .../snapshots/Module#FFI.verified.cs | 636 +- .../Module.net10#DemoTable.verified.cs | 107 + .../snapshots/Module.net10#FFI.verified.cs | 1416 ++++ ...e.net10#Reducers.DemoProcedure.verified.cs | 21 + ...ule.net10#Reducers.DemoReducer.verified.cs | 21 + .../snapshots/Type#DemoType.verified.cs | 2 +- .../Module#BTreeMultiColumn.verified.cs | 2 +- .../snapshots/Module#BTreeViews.verified.cs | 2 +- .../server/snapshots/Module#FFI.verified.cs | 1503 +++- .../Module#MultiTableRow.verified.cs | 2 +- .../snapshots/Module#PublicTable.verified.cs | 2 +- ...ltipleUniqueIndexesHadSameName.verified.cs | 2 +- ...Module#Timers.SendMessageTimer.verified.cs | 2 +- .../Module.net10#BTreeMultiColumn.verified.cs | 117 + .../Module.net10#BTreeViews.verified.cs | 120 + .../snapshots/Module.net10#FFI.verified.cs | 4439 ++++++++++++ ...#MultiTableRow.InsertMultiData.verified.cs | 21 + .../Module.net10#MultiTableRow.verified.cs | 115 + .../Module.net10#PrivateTable.verified.cs | 92 + .../Module.net10#PublicTable.verified.cs | 380 + ...dule.net10#Reducers.InsertData.verified.cs | 21 + ...t10#Reducers.ScheduleImmediate.verified.cs | 21 + ...ltipleUniqueIndexesHadSameName.verified.cs | 121 + ...espaces.AndClasses.InsertData2.verified.cs | 24 + .../Module.net10#Timers.Init.verified.cs | 21 + ....net10#Timers.SendMessageTimer.verified.cs | 123 + ...10#Timers.SendScheduledMessage.verified.cs | 23 + .../Type#ContainsNestedLists.verified.cs | 2 +- .../snapshots/Type#CustomClass.verified.cs | 2 +- .../Type#CustomNestedClass.verified.cs | 2 +- .../snapshots/Type#CustomRecord.verified.cs | 2 +- .../snapshots/Type#CustomStruct.verified.cs | 2 +- .../Type#CustomTaggedEnum.verified.cs | 9 +- ...pe#FormerlyForbiddenFieldNames.verified.cs | 2 +- ...p_dumpName=LegacySubscribeAll.verified.txt | 6 + ...ump_dumpName=SubscribeApplied.verified.txt | 4 + 81 files changed, 19814 insertions(+), 650 deletions(-) create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#InAnotherNamespace.TestDuplicateTableName.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Player.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.InAnotherNamespace.TestDuplicateReducerName.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.OnReducerWithReservedPrefix.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind1.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind2.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerName.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerReturnType.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerWithoutContext.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.__ReducerWithReservedPrefix.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestAutoIncNotInteger.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestDefaultFieldValues.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestDuplicateTableName.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestIndexIssues.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.DummyScheduledReducer.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestTableTaggedEnum.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestUniqueNotEquatable.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10.verified.txt create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#DemoTable.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoProcedure.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoReducer.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#BTreeMultiColumn.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#BTreeViews.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.InsertMultiData.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#PrivateTable.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#PublicTable.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.InsertData.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.ScheduleImmediate.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#RegressionMultipleUniqueIndexesHadSameName.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.Init.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendMessageTimer.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendScheduledMessage.verified.cs diff --git a/crates/bindings-csharp/Codegen.Tests/TestInit.cs b/crates/bindings-csharp/Codegen.Tests/TestInit.cs index aff6f194409..e733c3aad52 100644 --- a/crates/bindings-csharp/Codegen.Tests/TestInit.cs +++ b/crates/bindings-csharp/Codegen.Tests/TestInit.cs @@ -55,7 +55,7 @@ public override void Write(VerifyJsonWriter writer, Diagnostic diag) { var line = lines[lineIdx]; // print the source line - comment.AppendLine(line.ToString()); + comment.AppendLine(line.ToString().TrimEnd()); // print squiggly line highlighting the location if (line.Span.Intersection(loc.SourceSpan) is { } intersection) { diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomClass.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomClass.verified.cs index c3ddd0f9ac9..0197c0b0e66 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomClass.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomClass.verified.cs @@ -48,7 +48,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new SpacetimeDB.BSATN.AggregateElement[] { new("IntField", IntFieldRW.GetAlgebraicType(registrar)), - new("StringField", StringFieldRW.GetAlgebraicType(registrar)) + new("StringField", StringFieldRW.GetAlgebraicType(registrar)), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomStruct.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomStruct.verified.cs index 4730a9cb550..f7b28a0e3fc 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomStruct.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomStruct.verified.cs @@ -50,7 +50,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new SpacetimeDB.BSATN.AggregateElement[] { new("IntField", IntFieldRW.GetAlgebraicType(registrar)), - new("StringField", StringFieldRW.GetAlgebraicType(registrar)) + new("StringField", StringFieldRW.GetAlgebraicType(registrar)), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomTaggedEnum.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomTaggedEnum.verified.cs index 0f6a93c3c41..b63a76c9365 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomTaggedEnum.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#CustomTaggedEnum.verified.cs @@ -27,10 +27,9 @@ public CustomTaggedEnum Read(System.IO.BinaryReader reader) { 0 => new IntVariant(IntVariantRW.Read(reader)), 1 => new StringVariant(StringVariantRW.Read(reader)), - _ - => throw new System.InvalidOperationException( - "Invalid tag value, this state should be unreachable." - ) + _ => throw new System.InvalidOperationException( + "Invalid tag value, this state should be unreachable." + ), }; } @@ -56,7 +55,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new SpacetimeDB.BSATN.AggregateElement[] { new("IntVariant", IntVariantRW.GetAlgebraicType(registrar)), - new("StringVariant", StringVariantRW.GetAlgebraicType(registrar)) + new("StringVariant", StringVariantRW.GetAlgebraicType(registrar)), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#PublicTable.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#PublicTable.verified.cs index e447adafb6e..630d6c9c7db 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#PublicTable.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/client/snapshots/Type#PublicTable.verified.cs @@ -157,7 +157,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new( "NullableReferenceField", NullableReferenceFieldRW.GetAlgebraicType(registrar) - ) + ), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt new file mode 100644 index 00000000000..63a906deab3 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt @@ -0,0 +1,738 @@ +[ + {/* + { + ctx.GetIdentity(); + ^^^^^^^^^^^ + return null; +*/ + Message: 'AnonymousViewContext' does not contain a definition for 'GetIdentity' and no accessible extension method 'GetIdentity' accepting a first argument of type 'AnonymousViewContext' could be found (are you missing a using directive or an assembly reference?), + Severity: Error, + Descriptor: { + Id: CS1061, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS1061), + MessageFormat: '{0}' does not contain a definition for '{1}' and no accessible extension method '{1}' accepting a first argument of type '{0}' could be found (are you missing a using directive or an assembly reference?), + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + + builder.RegisterClientVisibilityFilter(global::Module.MY_FILTER); + ^^^^^^^^^ + builder.RegisterClientVisibilityFilter(global::Module.MY_FOURTH_FILTER); +*/ + Message: 'Module.MY_FILTER' is inaccessible due to its protection level, + Severity: Error, + Descriptor: { + Id: CS0122, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0122), + MessageFormat: '{0}' is inaccessible due to its protection level, + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + { + ctx.Db.Player.Identity.Delete(0); + ^^^^^^ + return null; +*/ + Message: 'PlayerReadOnly.IdentityIndex' does not contain a definition for 'Delete' and no accessible extension method 'Delete' accepting a first argument of type 'PlayerReadOnly.IdentityIndex' could be found (are you missing a using directive or an assembly reference?), + Severity: Error, + Descriptor: { + Id: CS1061, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS1061), + MessageFormat: '{0}' does not contain a definition for '{1}' and no accessible extension method '{1}' accepting a first argument of type '{0}' could be found (are you missing a using directive or an assembly reference?), + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + { + ctx.Db.Player.Delete(new Player { Identity = new() }); + ^^^^^^ + return null; +*/ + Message: 'PlayerReadOnly' does not contain a definition for 'Delete' and no accessible extension method 'Delete' accepting a first argument of type 'PlayerReadOnly' could be found (are you missing a using directive or an assembly reference?), + Severity: Error, + Descriptor: { + Id: CS1061, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS1061), + MessageFormat: '{0}' does not contain a definition for '{1}' and no accessible extension method '{1}' accepting a first argument of type '{0}' could be found (are you missing a using directive or an assembly reference?), + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + { + ctx.Db.Player.Insert(new Player { Identity = new() }); + ^^^^^^ + return new Player { Identity = new() }; +*/ + Message: 'PlayerReadOnly' does not contain a definition for 'Insert' and no accessible extension method 'Insert' accepting a first argument of type 'PlayerReadOnly' could be found (are you missing a using directive or an assembly reference?), + Severity: Error, + Descriptor: { + Id: CS1061, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS1061), + MessageFormat: '{0}' does not contain a definition for '{1}' and no accessible extension method '{1}' accepting a first argument of type '{0}' could be found (are you missing a using directive or an assembly reference?), + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + { + return ctx.Db.Player.Iter(); + ^^^^ + } +*/ + Message: 'PlayerReadOnly' does not contain a definition for 'Iter' and no accessible extension method 'Iter' accepting a first argument of type 'PlayerReadOnly' could be found (are you missing a using directive or an assembly reference?), + Severity: Error, + Descriptor: { + Id: CS1061, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS1061), + MessageFormat: '{0}' does not contain a definition for '{1}' and no accessible extension method '{1}' accepting a first argument of type '{0}' could be found (are you missing a using directive or an assembly reference?), + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + { + ctx.Db.Player.Iter(); + ^^^^ + return null; +*/ + Message: 'PlayerReadOnly' does not contain a definition for 'Iter' and no accessible extension method 'Iter' accepting a first argument of type 'PlayerReadOnly' could be found (are you missing a using directive or an assembly reference?), + Severity: Error, + Descriptor: { + Id: CS1061, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS1061), + MessageFormat: '{0}' does not contain a definition for '{1}' and no accessible extension method '{1}' accepting a first argument of type '{0}' could be found (are you missing a using directive or an assembly reference?), + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + // Valid Filter, but [ClientVisibilityFilter] is disabled + [SpacetimeDB.ClientVisibilityFilter] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + public static readonly Filter MY_FOURTH_FILTER = new Filter.Sql( +*/ + Message: 'SpacetimeDB.ClientVisibilityFilterAttribute' is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed., + Severity: Error, + Descriptor: { + Id: STDB_UNSTABLE, + Title: Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed., + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS9204), + MessageFormat: '{0}' is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed., + Category: Compiler, + DefaultSeverity: Warning, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + CustomObsolete + ] + } + }, + {/* + +partial struct TestTypeParams : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*/ + Message: 'TestTypeParams' does not implement interface member 'IEquatable.Equals(TestTypeParams?)', + Severity: Error, + Descriptor: { + Id: CS0535, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0535), + MessageFormat: '{0}' does not implement interface member '{1}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* +var ___hashUnsupportedSystemType = UnsupportedSystemType == null ? 0 : UnsupportedSystemType.GetHashCode(); +var ___hashUnresolvedType = UnresolvedType == null ? 0 : UnresolvedType.GetHashCode(); + ^^^^^^^^^^^ +var ___hashUnsupportedEnum = UnsupportedEnum.GetHashCode(); +*/ + Message: 'UnresolvedType' does not contain a definition for 'GetHashCode' and no accessible extension method 'GetHashCode' accepting a first argument of type 'UnresolvedType' could be found (are you missing a using directive or an assembly reference?), + Severity: Error, + Descriptor: { + Id: CS1061, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS1061), + MessageFormat: '{0}' does not contain a definition for '{1}' and no accessible extension method '{1}' accepting a first argument of type '{0}' could be found (are you missing a using directive or an assembly reference?), + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* +[SpacetimeDB.Table] +public partial struct TestDefaultFieldValues + ^^^^^^^^^^^^^^^^^^^^^^ +{ +*/ + Message: A 'struct' with field initializers must include an explicitly declared constructor., + Severity: Error, + Descriptor: { + Id: CS8983, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS8983), + MessageFormat: A 'struct' with field initializers must include an explicitly declared constructor., + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + + var returnValue = Module.ViewDefWrongContext((SpacetimeDB.ViewContext)ctx); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + var listSerializer = new SpacetimeDB.BSATN.List(); +*/ + Message: Argument 1: cannot convert from 'SpacetimeDB.ViewContext' to 'SpacetimeDB.ReducerContext', + Severity: Error, + Descriptor: { + Id: CS1503, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS1503), + MessageFormat: Argument {0}: cannot convert from '{1}' to '{2}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + builder.RegisterClientVisibilityFilter(global::Module.MY_SECOND_FILTER); + builder.RegisterClientVisibilityFilter(global::Module.MY_THIRD_FILTER); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + { +*/ + Message: Argument 1: cannot convert from 'string' to 'SpacetimeDB.Filter', + Severity: Error, + Descriptor: { + Id: CS1503, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS1503), + MessageFormat: Argument {0}: cannot convert from '{1}' to '{2}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + { + return ctx.Db.TestIndexIssues.TestUnexpectedColumns.Filter(0); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + } +*/ + Message: Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?), + Severity: Error, + Descriptor: { + Id: CS0266, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0266), + MessageFormat: Cannot implicitly convert type '{0}' to '{1}'. An explicit conversion exists (are you missing a cast?), + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + + var returnValue = Module.ViewDefNoContext((SpacetimeDB.ViewContext)ctx); + ^^^^^^^^^^^^^^^^ + var listSerializer = new SpacetimeDB.BSATN.List(); +*/ + Message: No overload for method 'ViewDefNoContext' takes 1 arguments, + Severity: Error, + Descriptor: { + Id: CS1501, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS1501), + MessageFormat: No overload for method '{0}' takes {1} arguments, + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + { + public global::SpacetimeDB.Table TestDuplicateTableName() => new AssemblyDescriptor.Queries().TestDuplicateTableName(); + ^^^^^^^^^^^^^^^^^^^^^^ + } +*/ + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(793)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(983)]', + Severity: Error, + Descriptor: { + Id: CS0121, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0121), + MessageFormat: The call is ambiguous between the following methods or properties: '{0}' and '{1}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + { + public global::SpacetimeDB.Table TestDuplicateTableName() => new AssemblyDescriptor.Queries().TestDuplicateTableName(); + ^^^^^^^^^^^^^^^^^^^^^^ + } +*/ + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(793)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(983)]', + Severity: Error, + Descriptor: { + Id: CS0121, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0121), + MessageFormat: The call is ambiguous between the following methods or properties: '{0}' and '{1}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName("diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestDuplicateTableName"); + return new(tableName, new TestDuplicateTableNameCols(tableName), new TestDuplicateTableNameIxCols(tableName)); + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + } +*/ + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(773)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(963)]', + Severity: Error, + Descriptor: { + Id: CS0121, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0121), + MessageFormat: The call is ambiguous between the following methods or properties: '{0}' and '{1}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName("diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestDuplicateTableName"); + return new(tableName, new TestDuplicateTableNameCols(tableName), new TestDuplicateTableNameIxCols(tableName)); + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + } +*/ + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(773)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(963)]', + Severity: Error, + Descriptor: { + Id: CS0121, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0121), + MessageFormat: The call is ambiguous between the following methods or properties: '{0}' and '{1}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName("diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestDuplicateTableName"); + return new(tableName, new TestDuplicateTableNameCols(tableName), new TestDuplicateTableNameIxCols(tableName)); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + } +*/ + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(783)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(973)]', + Severity: Error, + Descriptor: { + Id: CS0121, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0121), + MessageFormat: The call is ambiguous between the following methods or properties: '{0}' and '{1}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName("diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestDuplicateTableName"); + return new(tableName, new TestDuplicateTableNameCols(tableName), new TestDuplicateTableNameIxCols(tableName)); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + } +*/ + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(783)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(973)]', + Severity: Error, + Descriptor: { + Id: CS0121, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0121), + MessageFormat: The call is ambiguous between the following methods or properties: '{0}' and '{1}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + } + public readonly struct TestDuplicateTableNameCols + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + { +*/ + Message: The namespace 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C' already contains a definition for 'TestDuplicateTableNameCols', + Severity: Error, + Descriptor: { + Id: CS0101, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0101), + MessageFormat: The namespace '{1}' already contains a definition for '{0}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + + public readonly struct TestDuplicateTableNameIxCols + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + { +*/ + Message: The namespace 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C' already contains a definition for 'TestDuplicateTableNameIxCols', + Severity: Error, + Descriptor: { + Id: CS0101, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0101), + MessageFormat: The namespace '{1}' already contains a definition for '{0}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + Params: [], + ReturnType: new SpacetimeDB.BSATN.ValueOption().GetAlgebraicType(registrar) + ^^^^^ +); +*/ + Message: The type name 'BSATN' does not exist in the type 'NotSpacetimeType', + Severity: Error, + Descriptor: { + Id: CS0426, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0426), + MessageFormat: The type name '{0}' does not exist in the type '{1}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + var returnValue = Module.ViewDefReturnsNotASpacetimeType((SpacetimeDB.AnonymousViewContext)ctx); + var listSerializer = SpacetimeDB.BSATN.ValueOption.GetListSerializer(); + ^^^^^ + var listValue = ModuleRegistration.ToListOrEmpty(returnValue); +*/ + Message: The type name 'BSATN' does not exist in the type 'NotSpacetimeType', + Severity: Error, + Descriptor: { + Id: CS0426, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0426), + MessageFormat: The type name '{0}' does not exist in the type '{1}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + { + internal static readonly TRW FieldRW = new(); + ^^^ + +*/ + Message: The type or namespace name 'TRW' could not be found (are you missing a using directive or an assembly reference?), + Severity: Error, + Descriptor: { + Id: CS0246, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0246), + MessageFormat: The type or namespace name '{0}' could not be found (are you missing a using directive or an assembly reference?), + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + public Exception UnsupportedSystemType; + public UnresolvedType UnresolvedType; + ^^^^^^^^^^^^^^ + public LocalEnum UnsupportedEnum; +*/ + Message: The type or namespace name 'UnresolvedType' could not be found (are you missing a using directive or an assembly reference?), + Severity: Error, + Descriptor: { + Id: CS0246, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0246), + MessageFormat: The type or namespace name '{0}' could not be found (are you missing a using directive or an assembly reference?), + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + { + public global::SpacetimeDB.Table TestDuplicateTableName() + ^^^^^^^^^^^^^^^^^^^^^^ + { +*/ + Message: Type 'AssemblyDescriptor.Queries' already defines a member called 'TestDuplicateTableName' with the same parameter types, + Severity: Error, + Descriptor: { + Id: CS0111, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0111), + MessageFormat: Type '{1}' already defines a member called '{0}' with the same parameter types, + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + { + public global::SpacetimeDB.Table TestDuplicateTableName() => new AssemblyDescriptor.Queries().TestDuplicateTableName(); + ^^^^^^^^^^^^^^^^^^^^^^ + } +*/ + Message: Type 'QueryTableExtensions' already defines a member called 'TestDuplicateTableName' with the same parameter types, + Severity: Error, + Descriptor: { + Id: CS0111, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0111), + MessageFormat: Type '{1}' already defines a member called '{0}' with the same parameter types, + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + + internal TestDuplicateTableNameCols(global::SpacetimeDB.SqlTableName tableName) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + { +*/ + Message: Type 'TestDuplicateTableNameCols' already defines a member called 'TestDuplicateTableNameCols' with the same parameter types, + Severity: Error, + Descriptor: { + Id: CS0111, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0111), + MessageFormat: Type '{1}' already defines a member called '{0}' with the same parameter types, + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + + internal TestDuplicateTableNameIxCols(global::SpacetimeDB.SqlTableName tableName) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + { +*/ + Message: Type 'TestDuplicateTableNameIxCols' already defines a member called 'TestDuplicateTableNameIxCols' with the same parameter types, + Severity: Error, + Descriptor: { + Id: CS0111, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0111), + MessageFormat: Type '{1}' already defines a member called '{0}' with the same parameter types, + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + +partial struct TestTypeParams : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite { + ^^^^^^^^^^^^^^ + +*/ + Message: Using the generic type 'TestTypeParams' requires 1 type arguments, + Severity: Error, + Descriptor: { + Id: CS0305, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0305), + MessageFormat: Using the generic {1} '{0}' requires {2} type arguments, + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + } +] \ No newline at end of file diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.verified.txt b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.verified.txt index 8d65f041f30..e3c89b1d9d8 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.verified.txt +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.verified.txt @@ -23,10 +23,10 @@ } }, {/* - - SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_FILTER); - ^^^^^^^^^ -SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_FOURTH_FILTER); + + builder.RegisterClientVisibilityFilter(global::Module.MY_FILTER); + ^^^^^^^^^ + builder.RegisterClientVisibilityFilter(global::Module.MY_FOURTH_FILTER); */ Message: 'Module.MY_FILTER' is inaccessible due to its protection level, Severity: Error, @@ -253,7 +253,7 @@ public partial struct TestDefaultFieldValues } }, {/* - + var returnValue = Module.ViewDefWrongContext((SpacetimeDB.ViewContext)ctx); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ var listSerializer = new SpacetimeDB.BSATN.List(); @@ -276,9 +276,9 @@ public partial struct TestDefaultFieldValues } }, {/* -SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_SECOND_FILTER); -SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_THIRD_FILTER); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + builder.RegisterClientVisibilityFilter(global::Module.MY_SECOND_FILTER); + builder.RegisterClientVisibilityFilter(global::Module.MY_THIRD_FILTER); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ { */ Message: Argument 1: cannot convert from 'string' to 'SpacetimeDB.Filter', @@ -322,7 +322,7 @@ SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_THI } }, {/* - + var returnValue = Module.ViewDefNoContext((SpacetimeDB.ViewContext)ctx); ^^^^^^^^^^^^^^^^ var listSerializer = new SpacetimeDB.BSATN.List(); @@ -345,10 +345,10 @@ SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_THI } }, {/* - public global::SpacetimeDB.Table TestDuplicateTableName() => - new("TestDuplicateTableName", new TestDuplicateTableNameCols("TestDuplicateTableName"), new TestDuplicateTableNameIxCols("TestDuplicateTableName")); - ^^^^^^^^^^^^^^^^^^^^^^^^^^ -} + public global::SpacetimeDB.Table TestDuplicateTableName() => + new("TestDuplicateTableName", new TestDuplicateTableNameCols("TestDuplicateTableName"), new TestDuplicateTableNameIxCols("TestDuplicateTableName")); + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + } */ Message: The call is ambiguous between the following methods or properties: 'TestDuplicateTableNameCols.TestDuplicateTableNameCols(string)' and 'TestDuplicateTableNameCols.TestDuplicateTableNameCols(string)', Severity: Error, @@ -368,10 +368,10 @@ SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_THI } }, {/* - public global::SpacetimeDB.Table TestDuplicateTableName() => - new("TestDuplicateTableName", new TestDuplicateTableNameCols("TestDuplicateTableName"), new TestDuplicateTableNameIxCols("TestDuplicateTableName")); - ^^^^^^^^^^^^^^^^^^^^^^^^^^ -} + public global::SpacetimeDB.Table TestDuplicateTableName() => + new("TestDuplicateTableName", new TestDuplicateTableNameCols("TestDuplicateTableName"), new TestDuplicateTableNameIxCols("TestDuplicateTableName")); + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + } */ Message: The call is ambiguous between the following methods or properties: 'TestDuplicateTableNameCols.TestDuplicateTableNameCols(string)' and 'TestDuplicateTableNameCols.TestDuplicateTableNameCols(string)', Severity: Error, @@ -391,10 +391,10 @@ SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_THI } }, {/* - public global::SpacetimeDB.Table TestDuplicateTableName() => - new("TestDuplicateTableName", new TestDuplicateTableNameCols("TestDuplicateTableName"), new TestDuplicateTableNameIxCols("TestDuplicateTableName")); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -} + public global::SpacetimeDB.Table TestDuplicateTableName() => + new("TestDuplicateTableName", new TestDuplicateTableNameCols("TestDuplicateTableName"), new TestDuplicateTableNameIxCols("TestDuplicateTableName")); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + } */ Message: The call is ambiguous between the following methods or properties: 'TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(string)' and 'TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(string)', Severity: Error, @@ -414,10 +414,10 @@ SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_THI } }, {/* - public global::SpacetimeDB.Table TestDuplicateTableName() => - new("TestDuplicateTableName", new TestDuplicateTableNameCols("TestDuplicateTableName"), new TestDuplicateTableNameIxCols("TestDuplicateTableName")); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -} + public global::SpacetimeDB.Table TestDuplicateTableName() => + new("TestDuplicateTableName", new TestDuplicateTableNameCols("TestDuplicateTableName"), new TestDuplicateTableNameIxCols("TestDuplicateTableName")); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + } */ Message: The call is ambiguous between the following methods or properties: 'TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(string)' and 'TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(string)', Severity: Error, @@ -437,10 +437,10 @@ SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_THI } }, {/* -} -public readonly struct TestDuplicateTableNameCols - ^^^^^^^^^^^^^^^^^^^^^^^^^^ -{ + } + public readonly struct TestDuplicateTableNameCols + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + { */ Message: The namespace 'SpacetimeDB' already contains a definition for 'TestDuplicateTableNameCols', Severity: Error, @@ -461,9 +461,9 @@ public readonly struct TestDuplicateTableNameCols }, {/* -public readonly struct TestDuplicateTableNameIxCols - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -{ + public readonly struct TestDuplicateTableNameIxCols + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + { */ Message: The namespace 'SpacetimeDB' already contains a definition for 'TestDuplicateTableNameIxCols', Severity: Error, @@ -575,10 +575,10 @@ public readonly struct TestDuplicateTableNameIxCols } }, {/* -{ - public global::SpacetimeDB.Table TestDuplicateTableName() => - ^^^^^^^^^^^^^^^^^^^^^^ - new("TestDuplicateTableName", new TestDuplicateTableNameCols("TestDuplicateTableName"), new TestDuplicateTableNameIxCols("TestDuplicateTableName")); + { + public global::SpacetimeDB.Table TestDuplicateTableName() => + ^^^^^^^^^^^^^^^^^^^^^^ + new("TestDuplicateTableName", new TestDuplicateTableNameCols("TestDuplicateTableName"), new TestDuplicateTableNameIxCols("TestDuplicateTableName")); */ Message: Type 'QueryBuilder' already defines a member called 'TestDuplicateTableName' with the same parameter types, Severity: Error, @@ -599,9 +599,9 @@ public readonly struct TestDuplicateTableNameIxCols }, {/* - internal TestDuplicateTableNameCols(string tableName) - ^^^^^^^^^^^^^^^^^^^^^^^^^^ - { + internal TestDuplicateTableNameCols(string tableName) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + { */ Message: Type 'TestDuplicateTableNameCols' already defines a member called 'TestDuplicateTableNameCols' with the same parameter types, Severity: Error, @@ -622,9 +622,9 @@ public readonly struct TestDuplicateTableNameIxCols }, {/* - internal TestDuplicateTableNameIxCols(string tableName) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - { + internal TestDuplicateTableNameIxCols(string tableName) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + { */ Message: Type 'TestDuplicateTableNameIxCols' already defines a member called 'TestDuplicateTableNameIxCols' with the same parameter types, Severity: Error, diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs index e81f122020d..1b4b09a8e2c 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs @@ -1,20 +1,28 @@ //HintName: FFI.cs // #nullable enable -// The runtime already defines SpacetimeDB.Internal.LocalReadOnly in Runtime\Internal\Module.cs as an empty partial type. -// This is needed so every module build doesn't generate a full LocalReadOnly type, but just adds on to the existing. -// We extend it here with generated table accessors, and just need to suppress the duplicate-type warning. +// .NET 8 generates a module-local LocalReadOnly which shadows the runtime shell. #pragma warning disable CS0436 #pragma warning disable STDB_UNSTABLE +#if NET10_0_OR_GREATER +global using SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C; +#endif using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Internal = SpacetimeDB.Internal; using TxContext = SpacetimeDB.Internal.TxContext; +#if NET10_0_OR_GREATER +[assembly: global::SpacetimeDB.ModuleDescriptorAttribute( + typeof(global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor) +)] + +#endif namespace SpacetimeDB { +#if !NET10_0_OR_GREATER public readonly struct TestDuplicateTableNameCols { internal TestDuplicateTableNameCols(string tableName) { } @@ -644,9 +652,11 @@ public readonly partial struct QueryBuilder new TestUniqueNotEquatableIxCols("TestUniqueNotEquatable") ); } +#endif public static class Handlers { } +#if !NET10_0_OR_GREATER public sealed record ReducerContext : DbContext, Internal.IReducerContext { public global::SpacetimeDB.ModuleEnvironment Env => default; @@ -909,17 +919,1132 @@ internal ViewContext(Identity sender, Internal.LocalReadOnly db) } } - public sealed record AnonymousViewContext - : DbContext, - Internal.IAnonymousViewContext + public sealed record AnonymousViewContext + : DbContext, + Internal.IAnonymousViewContext + { + public global::SpacetimeDB.ModuleEnvironment Env => default; + public QueryBuilder From => default; + + internal AnonymousViewContext(Internal.LocalReadOnly db) + : base(db) { } + } +#endif +} + +#if NET10_0_OR_GREATER +namespace SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +{ + public static partial class AssemblyDescriptor + { + public const string LifecycleReducers = + "Reducers.TestDuplicateReducerKind1 (Init), Reducers.TestDuplicateReducerKind2 (Init)"; + public const int ReducerCount = 8; + public const int ProcedureCount = 0; + public const int HttpHandlerCount = 0; + public const int ViewCount = 12; + public const int AnonymousViewCount = 4; + + public static global::SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink error + ) => + global::ModuleRegistration.CallLocalReducer( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink result_sink + ) => + global::ModuleRegistration.CallLocalProcedure( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource request, + global::SpacetimeDB.Internal.BytesSource request_body, + global::SpacetimeDB.Internal.BytesSink response_sink, + global::SpacetimeDB.Internal.BytesSink response_body_sink + ) => + global::ModuleRegistration.CallLocalHttpHandler( + id, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => + global::ModuleRegistration.CallLocalView( + id, + sender_0, + sender_1, + sender_2, + sender_3, + args, + sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => global::ModuleRegistration.CallLocalAnonymousView(id, args, sink); + + public static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null + ) => global::ModuleRegistration.Register(builder, httpBuilder); + + public readonly struct Tables + { + public global::SpacetimeDB.Internal.TableHandles.Player Player => new(); + public global::SpacetimeDB.Internal.TableHandles.TestAutoIncNotInteger TestAutoIncNotInteger => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestDefaultFieldValues TestDefaultFieldValues => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestDuplicateTableName TestDuplicateTableName => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestIndexIssues TestIndexIssues => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithMissingScheduleAtField TestScheduleWithMissingScheduleAtField => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithoutPrimaryKey TestScheduleWithoutPrimaryKey => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithoutScheduleAt TestScheduleWithoutScheduleAt => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithWrongPrimaryKeyType TestScheduleWithWrongPrimaryKeyType => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithWrongScheduleAtType TestScheduleWithWrongScheduleAtType => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestUniqueNotEquatable TestUniqueNotEquatable => + new(); + } + + public readonly struct ReadOnlyTables + { + public global::SpacetimeDB.Internal.ViewHandles.PlayerReadOnly Player => new(); + public global::SpacetimeDB.Internal.ViewHandles.TestAutoIncNotIntegerReadOnly TestAutoIncNotInteger => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestDefaultFieldValuesReadOnly TestDefaultFieldValues => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestDuplicateTableNameReadOnly TestDuplicateTableName => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestIndexIssuesReadOnly TestIndexIssues => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithMissingScheduleAtFieldReadOnly TestScheduleWithMissingScheduleAtField => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithoutPrimaryKeyReadOnly TestScheduleWithoutPrimaryKey => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithoutScheduleAtReadOnly TestScheduleWithoutScheduleAt => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly TestScheduleWithWrongPrimaryKeyType => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly TestScheduleWithWrongScheduleAtType => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestUniqueNotEquatableReadOnly TestUniqueNotEquatable => + new(); + } + + public readonly partial struct Queries { } + } + + public static class LocalTableExtensions + { + extension(global::SpacetimeDB.Local db) + { + public global::SpacetimeDB.Internal.TableHandles.Player Player => new(); + public global::SpacetimeDB.Internal.TableHandles.TestAutoIncNotInteger TestAutoIncNotInteger => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestDefaultFieldValues TestDefaultFieldValues => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestDuplicateTableName TestDuplicateTableName => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestIndexIssues TestIndexIssues => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithMissingScheduleAtField TestScheduleWithMissingScheduleAtField => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithoutPrimaryKey TestScheduleWithoutPrimaryKey => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithoutScheduleAt TestScheduleWithoutScheduleAt => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithWrongPrimaryKeyType TestScheduleWithWrongPrimaryKeyType => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithWrongScheduleAtType TestScheduleWithWrongScheduleAtType => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestUniqueNotEquatable TestUniqueNotEquatable => + new(); + } + } + + public static class ReadOnlyTableExtensions + { + extension(global::SpacetimeDB.Internal.LocalReadOnly db) + { + public global::SpacetimeDB.Internal.ViewHandles.PlayerReadOnly Player => new(); + public global::SpacetimeDB.Internal.ViewHandles.TestAutoIncNotIntegerReadOnly TestAutoIncNotInteger => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestDefaultFieldValuesReadOnly TestDefaultFieldValues => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestDuplicateTableNameReadOnly TestDuplicateTableName => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestIndexIssuesReadOnly TestIndexIssues => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithMissingScheduleAtFieldReadOnly TestScheduleWithMissingScheduleAtField => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithoutPrimaryKeyReadOnly TestScheduleWithoutPrimaryKey => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithoutScheduleAtReadOnly TestScheduleWithoutScheduleAt => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly TestScheduleWithWrongPrimaryKeyType => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly TestScheduleWithWrongScheduleAtType => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestUniqueNotEquatableReadOnly TestUniqueNotEquatable => + new(); + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) { } + } + + public readonly struct TestDuplicateTableNameCols + { + internal TestDuplicateTableNameCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public readonly struct TestDuplicateTableNameIxCols + { + internal TestDuplicateTableNameIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::InAnotherNamespace.TestDuplicateTableName, + TestDuplicateTableNameCols, + TestDuplicateTableNameIxCols + > TestDuplicateTableName() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDuplicateTableName" + ); + return new( + tableName, + new TestDuplicateTableNameCols(tableName), + new TestDuplicateTableNameIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::InAnotherNamespace.TestDuplicateTableName, + TestDuplicateTableNameCols, + TestDuplicateTableNameIxCols + > TestDuplicateTableName() => new AssemblyDescriptor.Queries().TestDuplicateTableName(); + } + } + + public readonly struct PlayerCols + { + public readonly global::SpacetimeDB.Col Identity; + + internal PlayerCols(global::SpacetimeDB.SqlTableName tableName) + { + Identity = new global::SpacetimeDB.Col( + tableName, + "Identity" + ); + } + } + + public readonly struct PlayerIxCols + { + internal PlayerIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table Player() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "Player" + ); + return new(tableName, new PlayerCols(tableName), new PlayerIxCols(tableName)); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table Player() => + new AssemblyDescriptor.Queries().Player(); + } + } + + public readonly struct TestAutoIncNotIntegerCols + { + public readonly global::SpacetimeDB.Col AutoIncField; + public readonly global::SpacetimeDB.Col< + global::TestAutoIncNotInteger, + string + > IdentityField; + + internal TestAutoIncNotIntegerCols(global::SpacetimeDB.SqlTableName tableName) + { + AutoIncField = new global::SpacetimeDB.Col( + tableName, + "AutoIncField" + ); + IdentityField = new global::SpacetimeDB.Col( + tableName, + "IdentityField" + ); + } + } + + public readonly struct TestAutoIncNotIntegerIxCols + { + internal TestAutoIncNotIntegerIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestAutoIncNotInteger, + TestAutoIncNotIntegerCols, + TestAutoIncNotIntegerIxCols + > TestAutoIncNotInteger() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestAutoIncNotInteger" + ); + return new( + tableName, + new TestAutoIncNotIntegerCols(tableName), + new TestAutoIncNotIntegerIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestAutoIncNotInteger, + TestAutoIncNotIntegerCols, + TestAutoIncNotIntegerIxCols + > TestAutoIncNotInteger() => new AssemblyDescriptor.Queries().TestAutoIncNotInteger(); + } + } + + public readonly struct TestDefaultFieldValuesCols + { + public readonly global::SpacetimeDB.Col UniqueField; + public readonly global::SpacetimeDB.Col< + global::TestDefaultFieldValues, + string + > DefaultString; + public readonly global::SpacetimeDB.Col DefaultBool; + public readonly global::SpacetimeDB.Col DefaultI8; + public readonly global::SpacetimeDB.Col DefaultU8; + public readonly global::SpacetimeDB.Col DefaultI16; + public readonly global::SpacetimeDB.Col DefaultU16; + public readonly global::SpacetimeDB.Col DefaultI32; + public readonly global::SpacetimeDB.Col DefaultU32; + public readonly global::SpacetimeDB.Col DefaultI64; + public readonly global::SpacetimeDB.Col DefaultU64; + public readonly global::SpacetimeDB.Col DefaultHex; + public readonly global::SpacetimeDB.Col DefaultBin; + public readonly global::SpacetimeDB.Col DefaultF32; + public readonly global::SpacetimeDB.Col DefaultF64; + public readonly global::SpacetimeDB.Col DefaultEnum; + public readonly global::SpacetimeDB.Col< + global::TestDefaultFieldValues, + MyStruct + > DefaultNull; + + internal TestDefaultFieldValuesCols(global::SpacetimeDB.SqlTableName tableName) + { + UniqueField = new global::SpacetimeDB.Col( + tableName, + "UniqueField" + ); + DefaultString = new global::SpacetimeDB.Col( + tableName, + "DefaultString" + ); + DefaultBool = new global::SpacetimeDB.Col( + tableName, + "DefaultBool" + ); + DefaultI8 = new global::SpacetimeDB.Col( + tableName, + "DefaultI8" + ); + DefaultU8 = new global::SpacetimeDB.Col( + tableName, + "DefaultU8" + ); + DefaultI16 = new global::SpacetimeDB.Col( + tableName, + "DefaultI16" + ); + DefaultU16 = new global::SpacetimeDB.Col( + tableName, + "DefaultU16" + ); + DefaultI32 = new global::SpacetimeDB.Col( + tableName, + "DefaultI32" + ); + DefaultU32 = new global::SpacetimeDB.Col( + tableName, + "DefaultU32" + ); + DefaultI64 = new global::SpacetimeDB.Col( + tableName, + "DefaultI64" + ); + DefaultU64 = new global::SpacetimeDB.Col( + tableName, + "DefaultU64" + ); + DefaultHex = new global::SpacetimeDB.Col( + tableName, + "DefaultHex" + ); + DefaultBin = new global::SpacetimeDB.Col( + tableName, + "DefaultBin" + ); + DefaultF32 = new global::SpacetimeDB.Col( + tableName, + "DefaultF32" + ); + DefaultF64 = new global::SpacetimeDB.Col( + tableName, + "DefaultF64" + ); + DefaultEnum = new global::SpacetimeDB.Col( + tableName, + "DefaultEnum" + ); + DefaultNull = new global::SpacetimeDB.Col( + tableName, + "DefaultNull" + ); + } + } + + public readonly struct TestDefaultFieldValuesIxCols + { + internal TestDefaultFieldValuesIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestDefaultFieldValues, + TestDefaultFieldValuesCols, + TestDefaultFieldValuesIxCols + > TestDefaultFieldValues() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDefaultFieldValues" + ); + return new( + tableName, + new TestDefaultFieldValuesCols(tableName), + new TestDefaultFieldValuesIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestDefaultFieldValues, + TestDefaultFieldValuesCols, + TestDefaultFieldValuesIxCols + > TestDefaultFieldValues() => new AssemblyDescriptor.Queries().TestDefaultFieldValues(); + } + } + + public readonly struct TestDuplicateTableNameCols + { + internal TestDuplicateTableNameCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public readonly struct TestDuplicateTableNameIxCols + { + internal TestDuplicateTableNameIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestDuplicateTableName, + TestDuplicateTableNameCols, + TestDuplicateTableNameIxCols + > TestDuplicateTableName() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDuplicateTableName" + ); + return new( + tableName, + new TestDuplicateTableNameCols(tableName), + new TestDuplicateTableNameIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestDuplicateTableName, + TestDuplicateTableNameCols, + TestDuplicateTableNameIxCols + > TestDuplicateTableName() => new AssemblyDescriptor.Queries().TestDuplicateTableName(); + } + } + + public readonly struct TestIndexIssuesCols + { + public readonly global::SpacetimeDB.Col SelfIndexingColumn; + public readonly global::SpacetimeDB.Col< + global::TestIndexIssues, + int + > SecondaryIndexingColumn; + + internal TestIndexIssuesCols(global::SpacetimeDB.SqlTableName tableName) + { + SelfIndexingColumn = new global::SpacetimeDB.Col( + tableName, + "SelfIndexingColumn" + ); + SecondaryIndexingColumn = new global::SpacetimeDB.Col( + tableName, + "SecondaryIndexingColumn" + ); + } + } + + public readonly struct TestIndexIssuesIxCols + { + public readonly global::SpacetimeDB.IxCol SelfIndexingColumn; + public readonly global::SpacetimeDB.IxCol< + global::TestIndexIssues, + int + > SecondaryIndexingColumn; + + internal TestIndexIssuesIxCols(global::SpacetimeDB.SqlTableName tableName) + { + SelfIndexingColumn = new global::SpacetimeDB.IxCol( + tableName, + "SelfIndexingColumn" + ); + SecondaryIndexingColumn = new global::SpacetimeDB.IxCol( + tableName, + "SecondaryIndexingColumn" + ); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestIndexIssues, + TestIndexIssuesCols, + TestIndexIssuesIxCols + > TestIndexIssues() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues" + ); + return new( + tableName, + new TestIndexIssuesCols(tableName), + new TestIndexIssuesIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestIndexIssues, + TestIndexIssuesCols, + TestIndexIssuesIxCols + > TestIndexIssues() => new AssemblyDescriptor.Queries().TestIndexIssues(); + } + } + + public readonly struct TestScheduleWithoutPrimaryKeyCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithoutPrimaryKeyCols(global::SpacetimeDB.SqlTableName tableName) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithoutPrimaryKeyIxCols + { + internal TestScheduleWithoutPrimaryKeyIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithoutPrimaryKeyCols, + TestScheduleWithoutPrimaryKeyIxCols + > TestScheduleWithoutPrimaryKey() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutPrimaryKey" + ); + return new( + tableName, + new TestScheduleWithoutPrimaryKeyCols(tableName), + new TestScheduleWithoutPrimaryKeyIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithoutPrimaryKeyCols, + TestScheduleWithoutPrimaryKeyIxCols + > TestScheduleWithoutPrimaryKey() => + new AssemblyDescriptor.Queries().TestScheduleWithoutPrimaryKey(); + } + } + + public readonly struct TestScheduleWithWrongPrimaryKeyTypeCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithWrongPrimaryKeyTypeCols(global::SpacetimeDB.SqlTableName tableName) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithWrongPrimaryKeyTypeIxCols + { + public readonly global::SpacetimeDB.IxCol IdWrongType; + + internal TestScheduleWithWrongPrimaryKeyTypeIxCols( + global::SpacetimeDB.SqlTableName tableName + ) + { + IdWrongType = new global::SpacetimeDB.IxCol( + tableName, + "IdWrongType" + ); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithWrongPrimaryKeyTypeCols, + TestScheduleWithWrongPrimaryKeyTypeIxCols + > TestScheduleWithWrongPrimaryKeyType() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongPrimaryKeyType" + ); + return new( + tableName, + new TestScheduleWithWrongPrimaryKeyTypeCols(tableName), + new TestScheduleWithWrongPrimaryKeyTypeIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithWrongPrimaryKeyTypeCols, + TestScheduleWithWrongPrimaryKeyTypeIxCols + > TestScheduleWithWrongPrimaryKeyType() => + new AssemblyDescriptor.Queries().TestScheduleWithWrongPrimaryKeyType(); + } + } + + public readonly struct TestScheduleWithoutScheduleAtCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithoutScheduleAtCols(global::SpacetimeDB.SqlTableName tableName) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithoutScheduleAtIxCols + { + public readonly global::SpacetimeDB.IxCol IdCorrectType; + + internal TestScheduleWithoutScheduleAtIxCols(global::SpacetimeDB.SqlTableName tableName) + { + IdCorrectType = new global::SpacetimeDB.IxCol( + tableName, + "IdCorrectType" + ); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithoutScheduleAtCols, + TestScheduleWithoutScheduleAtIxCols + > TestScheduleWithoutScheduleAt() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutScheduleAt" + ); + return new( + tableName, + new TestScheduleWithoutScheduleAtCols(tableName), + new TestScheduleWithoutScheduleAtIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithoutScheduleAtCols, + TestScheduleWithoutScheduleAtIxCols + > TestScheduleWithoutScheduleAt() => + new AssemblyDescriptor.Queries().TestScheduleWithoutScheduleAt(); + } + } + + public readonly struct TestScheduleWithWrongScheduleAtTypeCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithWrongScheduleAtTypeCols(global::SpacetimeDB.SqlTableName tableName) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithWrongScheduleAtTypeIxCols + { + public readonly global::SpacetimeDB.IxCol IdCorrectType; + + internal TestScheduleWithWrongScheduleAtTypeIxCols( + global::SpacetimeDB.SqlTableName tableName + ) + { + IdCorrectType = new global::SpacetimeDB.IxCol( + tableName, + "IdCorrectType" + ); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithWrongScheduleAtTypeCols, + TestScheduleWithWrongScheduleAtTypeIxCols + > TestScheduleWithWrongScheduleAtType() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongScheduleAtType" + ); + return new( + tableName, + new TestScheduleWithWrongScheduleAtTypeCols(tableName), + new TestScheduleWithWrongScheduleAtTypeIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithWrongScheduleAtTypeCols, + TestScheduleWithWrongScheduleAtTypeIxCols + > TestScheduleWithWrongScheduleAtType() => + new AssemblyDescriptor.Queries().TestScheduleWithWrongScheduleAtType(); + } + } + + public readonly struct TestScheduleWithMissingScheduleAtFieldCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithMissingScheduleAtFieldCols( + global::SpacetimeDB.SqlTableName tableName + ) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithMissingScheduleAtFieldIxCols + { + internal TestScheduleWithMissingScheduleAtFieldIxCols( + global::SpacetimeDB.SqlTableName tableName + ) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithMissingScheduleAtFieldCols, + TestScheduleWithMissingScheduleAtFieldIxCols + > TestScheduleWithMissingScheduleAtField() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithMissingScheduleAtField" + ); + return new( + tableName, + new TestScheduleWithMissingScheduleAtFieldCols(tableName), + new TestScheduleWithMissingScheduleAtFieldIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithMissingScheduleAtFieldCols, + TestScheduleWithMissingScheduleAtFieldIxCols + > TestScheduleWithMissingScheduleAtField() => + new AssemblyDescriptor.Queries().TestScheduleWithMissingScheduleAtField(); + } + } + + public readonly struct TestUniqueNotEquatableCols + { + public readonly global::SpacetimeDB.Col UniqueField; + public readonly global::SpacetimeDB.Col< + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues + > PrimaryKeyField; + + internal TestUniqueNotEquatableCols(global::SpacetimeDB.SqlTableName tableName) + { + UniqueField = new global::SpacetimeDB.Col( + tableName, + "UniqueField" + ); + PrimaryKeyField = new global::SpacetimeDB.Col< + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues + >(tableName, "PrimaryKeyField"); + } + } + + public readonly struct TestUniqueNotEquatableIxCols + { + public readonly global::SpacetimeDB.IxCol< + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues + > PrimaryKeyField; + + internal TestUniqueNotEquatableIxCols(global::SpacetimeDB.SqlTableName tableName) + { + PrimaryKeyField = new global::SpacetimeDB.IxCol< + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues + >(tableName, "PrimaryKeyField"); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestUniqueNotEquatable, + TestUniqueNotEquatableCols, + TestUniqueNotEquatableIxCols + > TestUniqueNotEquatable() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestUniqueNotEquatable" + ); + return new( + tableName, + new TestUniqueNotEquatableCols(tableName), + new TestUniqueNotEquatableIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions { - public global::SpacetimeDB.ModuleEnvironment Env => default; - public QueryBuilder From => default; - - internal AnonymousViewContext(Internal.LocalReadOnly db) - : base(db) { } + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestUniqueNotEquatable, + TestUniqueNotEquatableCols, + TestUniqueNotEquatableIxCols + > TestUniqueNotEquatable() => new AssemblyDescriptor.Queries().TestUniqueNotEquatable(); + } } } +#endif namespace SpacetimeDB.Internal.TableHandles { @@ -946,14 +2071,14 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "Player_Identity_idx_btree", AccessorName: "Identity", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) + ), ], Constraints: [ global::SpacetimeDB.Internal.ITableView< Player, global::Player - >.MakeUniqueConstraint(0) + >.MakeUniqueConstraint(0), ], Sequences: [], TableType: SpacetimeDB.Internal.TableType.User, @@ -986,7 +2111,12 @@ public ulong Clear() => global::SpacetimeDB.Internal.ITableView.DoClear(); public sealed class IdentityUniqueIndex - : UniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + Player, + global::Player, + SpacetimeDB.Identity, + SpacetimeDB.Identity.BSATN + > { internal IdentityUniqueIndex() : base("Player_Identity_idx_btree") { } @@ -1038,14 +2168,14 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "TestAutoIncNotInteger_IdentityField_idx_btree", AccessorName: "IdentityField", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) - ) + ), ], Constraints: [ global::SpacetimeDB.Internal.ITableView< TestAutoIncNotInteger, global::TestAutoIncNotInteger - >.MakeUniqueConstraint(1) + >.MakeUniqueConstraint(1), ], Sequences: [ @@ -1056,7 +2186,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar global::SpacetimeDB.Internal.ITableView< TestAutoIncNotInteger, global::TestAutoIncNotInteger - >.MakeSequence(1) + >.MakeSequence(1), ], TableType: SpacetimeDB.Internal.TableType.User, TableAccess: SpacetimeDB.Internal.TableAccess.Private, @@ -1103,7 +2233,7 @@ public ulong Clear() => >.DoClear(); public sealed class IdentityFieldUniqueIndex - : UniqueIndex< + : global::SpacetimeDB.Internal.UniqueIndex< TestAutoIncNotInteger, global::TestAutoIncNotInteger, string, @@ -1150,14 +2280,14 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "TestDefaultFieldValues_UniqueField_idx_btree", AccessorName: "UniqueField", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) + ), ], Constraints: [ global::SpacetimeDB.Internal.ITableView< TestDefaultFieldValues, global::TestDefaultFieldValues - >.MakeUniqueConstraint(0) + >.MakeUniqueConstraint(0), ], Sequences: [], TableType: SpacetimeDB.Internal.TableType.User, @@ -1325,7 +2455,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "TestIndexIssues_SelfIndexingColumn_idx_btree", AccessorName: "TestUnexpectedColumns", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) + ), ], Constraints: [], Sequences: [], @@ -1681,14 +2811,14 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "TestScheduleWithoutScheduleAt_IdCorrectType_idx_btree", AccessorName: "IdCorrectType", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) - ) + ), ], Constraints: [ global::SpacetimeDB.Internal.ITableView< TestScheduleWithoutScheduleAt, global::TestScheduleIssues - >.MakeUniqueConstraint(1) + >.MakeUniqueConstraint(1), ], Sequences: [], TableType: SpacetimeDB.Internal.TableType.User, @@ -1736,7 +2866,7 @@ public ulong Clear() => >.DoClear(); public sealed class IdCorrectTypeUniqueIndex - : UniqueIndex< + : global::SpacetimeDB.Internal.UniqueIndex< TestScheduleWithoutScheduleAt, global::TestScheduleIssues, int, @@ -1786,14 +2916,14 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "TestScheduleWithWrongPrimaryKeyType_IdWrongType_idx_btree", AccessorName: "IdWrongType", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) + ), ], Constraints: [ global::SpacetimeDB.Internal.ITableView< TestScheduleWithWrongPrimaryKeyType, global::TestScheduleIssues - >.MakeUniqueConstraint(0) + >.MakeUniqueConstraint(0), ], Sequences: [], TableType: SpacetimeDB.Internal.TableType.User, @@ -1845,7 +2975,7 @@ public ulong Clear() => >.DoClear(); public sealed class IdWrongTypeUniqueIndex - : UniqueIndex< + : global::SpacetimeDB.Internal.UniqueIndex< TestScheduleWithWrongPrimaryKeyType, global::TestScheduleIssues, string, @@ -1895,14 +3025,14 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "TestScheduleWithWrongScheduleAtType_IdCorrectType_idx_btree", AccessorName: "IdCorrectType", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) - ) + ), ], Constraints: [ global::SpacetimeDB.Internal.ITableView< TestScheduleWithWrongScheduleAtType, global::TestScheduleIssues - >.MakeUniqueConstraint(1) + >.MakeUniqueConstraint(1), ], Sequences: [], TableType: SpacetimeDB.Internal.TableType.User, @@ -1954,7 +3084,7 @@ public ulong Clear() => >.DoClear(); public sealed class IdCorrectTypeUniqueIndex - : UniqueIndex< + : global::SpacetimeDB.Internal.UniqueIndex< TestScheduleWithWrongScheduleAtType, global::TestScheduleIssues, int, @@ -2009,7 +3139,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "TestUniqueNotEquatable_PrimaryKeyField_idx_btree", AccessorName: "PrimaryKeyField", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) - ) + ), ], Constraints: [ @@ -2020,7 +3150,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar global::SpacetimeDB.Internal.ITableView< TestUniqueNotEquatable, global::TestUniqueNotEquatable - >.MakeUniqueConstraint(1) + >.MakeUniqueConstraint(1), ], Sequences: [], TableType: SpacetimeDB.Internal.TableType.User, @@ -2068,7 +3198,7 @@ public ulong Clear() => >.DoClear(); public sealed class PrimaryKeyFieldUniqueIndex - : UniqueIndex< + : global::SpacetimeDB.Internal.UniqueIndex< TestUniqueNotEquatable, global::TestUniqueNotEquatable, TestEnumWithExplicitValues, @@ -3189,6 +4319,7 @@ internal PrimaryKeyFieldIndex() } } +#if !NET10_0_OR_GREATER namespace SpacetimeDB.Internal { public sealed partial class LocalReadOnly @@ -3216,6 +4347,7 @@ public sealed partial class LocalReadOnly new(); } } +#endif static class ModuleRegistration { @@ -3415,8 +4547,11 @@ public static List ToListOrEmpty(T? value) // Prevent trimming of FFI exports that are invoked from C and not visible to C# trimmer. [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, typeof(ModuleRegistration))] #endif - public static void Main() + public static void Main() => Initialize(); + + internal static void Initialize() { +#if !NET10_0_OR_GREATER SpacetimeDB.Internal.Module.SetReducerContextConstructor( (identity, connectionId, random, time) => new SpacetimeDB.ReducerContext(identity, connectionId, random, time) @@ -3427,133 +4562,141 @@ public static void Main() new SpacetimeDB.Internal.LocalReadOnly() ) ); - SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor( - () => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly()) + SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor(() => + new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly()) ); SpacetimeDB.Internal.Module.SetProcedureContextConstructor( (identity, connectionId, random, time) => new SpacetimeDB.ProcedureContext(identity, connectionId, random, time) ); - SpacetimeDB.Internal.Module.SetCaseConversionPolicy( - SpacetimeDB.CaseConversionPolicy.SnakeCase + SpacetimeDB.Internal.Module.SetHandlerContextConstructor( + (random, time) => new SpacetimeDB.HandlerContext(random, time) ); - SpacetimeDB.Internal.Module.RegisterExplicitIndexName( - "TestIndexIssues_SecondaryIndexingColumn_idx_btree", - "TestCanonicalNameWithoutAccessor" +#endif + +#if NET10_0_OR_GREATER + global::SpacetimeDB.Internal.Module.InstallNamespaces( + new global::SpacetimeDB.Internal.NamespaceRegistry( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + new global::System.Collections.Generic.KeyValuePair[] { } + ) + ); + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Register( + global::SpacetimeDB.Internal.Module.RootBuilder ); +#else + Register(global::SpacetimeDB.Internal.Module.RootBuilder); +#endif + } - SpacetimeDB.Internal.Module.SetHandlerContextConstructor( - (random, time) => new SpacetimeDB.HandlerContext(random, time) + internal static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null + ) + { + // HTTP routes retain the root routing API even for mounted modules. + httpBuilder ??= builder; + builder.SetCaseConversionPolicy(SpacetimeDB.CaseConversionPolicy.SnakeCase); + builder.RegisterExplicitIndexName( + "TestIndexIssues_SecondaryIndexingColumn_idx_btree", + "TestCanonicalNameWithoutAccessor" ); var __memoryStream = new MemoryStream(); var __writer = new BinaryWriter(__memoryStream); - SpacetimeDB.Internal.Module.RegisterReducer<__ReducerWithReservedPrefix>(); - SpacetimeDB.Internal.Module.RegisterReducer(); - SpacetimeDB.Internal.Module.RegisterReducer(); - SpacetimeDB.Internal.Module.RegisterReducer(); - SpacetimeDB.Internal.Module.RegisterReducer(); - SpacetimeDB.Internal.Module.RegisterReducer(); - SpacetimeDB.Internal.Module.RegisterReducer(); - SpacetimeDB.Internal.Module.RegisterReducer(); + builder.RegisterReducer<__ReducerWithReservedPrefix>(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); // IMPORTANT: The order in which we register views matters. // It must correspond to the order in which we call `GenerateDispatcherClass`. // See the comment on `GenerateDispatcherClass` for more explanation. - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterAnonymousView(); - SpacetimeDB.Internal.Module.RegisterAnonymousView(); - SpacetimeDB.Internal.Module.RegisterAnonymousView(); - SpacetimeDB.Internal.Module.RegisterAnonymousView(); - - SpacetimeDB.Internal.Module.RegisterViewPrimaryKey( - "view_primary_key_missing_column", - ["MissingIdentity"] - ); - SpacetimeDB.Internal.Module.RegisterViewPrimaryKey( - "view_primary_key_non_equatable_column", - ["Identity"] - ); - SpacetimeDB.Internal.Module.RegisterViewPrimaryKey( + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterAnonymousView(); + builder.RegisterAnonymousView(); + builder.RegisterAnonymousView(); + builder.RegisterAnonymousView(); + + builder.RegisterViewPrimaryKey("view_primary_key_missing_column", ["MissingIdentity"]); + builder.RegisterViewPrimaryKey("view_primary_key_non_equatable_column", ["Identity"]); + builder.RegisterViewPrimaryKey( "view_primary_key_uses_non_bsatn_partial_field", ["ExtraPartialIdentity"] ); - SpacetimeDB.Internal.Module.RegisterViewPrimaryKey( + builder.RegisterViewPrimaryKey( "view_primary_key_uses_wrong_source_name", ["renamed_identity"] ); - SpacetimeDB.Internal.Module.RegisterTable< - global::Player, - SpacetimeDB.Internal.TableHandles.Player - >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable(); + builder.RegisterTable< global::TestAutoIncNotInteger, - SpacetimeDB.Internal.TableHandles.TestAutoIncNotInteger + global::SpacetimeDB.Internal.TableHandles.TestAutoIncNotInteger >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::TestDefaultFieldValues, - SpacetimeDB.Internal.TableHandles.TestDefaultFieldValues + global::SpacetimeDB.Internal.TableHandles.TestDefaultFieldValues >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::TestDuplicateTableName, - SpacetimeDB.Internal.TableHandles.TestDuplicateTableName + global::SpacetimeDB.Internal.TableHandles.TestDuplicateTableName >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::TestIndexIssues, - SpacetimeDB.Internal.TableHandles.TestIndexIssues + global::SpacetimeDB.Internal.TableHandles.TestIndexIssues >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::TestScheduleIssues, - SpacetimeDB.Internal.TableHandles.TestScheduleWithMissingScheduleAtField + global::SpacetimeDB.Internal.TableHandles.TestScheduleWithMissingScheduleAtField >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::TestScheduleIssues, - SpacetimeDB.Internal.TableHandles.TestScheduleWithoutPrimaryKey + global::SpacetimeDB.Internal.TableHandles.TestScheduleWithoutPrimaryKey >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::TestScheduleIssues, - SpacetimeDB.Internal.TableHandles.TestScheduleWithoutScheduleAt + global::SpacetimeDB.Internal.TableHandles.TestScheduleWithoutScheduleAt >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::TestScheduleIssues, - SpacetimeDB.Internal.TableHandles.TestScheduleWithWrongPrimaryKeyType + global::SpacetimeDB.Internal.TableHandles.TestScheduleWithWrongPrimaryKeyType >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::TestScheduleIssues, - SpacetimeDB.Internal.TableHandles.TestScheduleWithWrongScheduleAtType + global::SpacetimeDB.Internal.TableHandles.TestScheduleWithWrongScheduleAtType >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::TestUniqueNotEquatable, - SpacetimeDB.Internal.TableHandles.TestUniqueNotEquatable + global::SpacetimeDB.Internal.TableHandles.TestUniqueNotEquatable >(); - SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_FILTER); - SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_FOURTH_FILTER); - SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_SECOND_FILTER); - SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_THIRD_FILTER); + builder.RegisterClientVisibilityFilter(global::Module.MY_FILTER); + builder.RegisterClientVisibilityFilter(global::Module.MY_FOURTH_FILTER); + builder.RegisterClientVisibilityFilter(global::Module.MY_SECOND_FILTER); + builder.RegisterClientVisibilityFilter(global::Module.MY_THIRD_FILTER); { var value = new SpacetimeDB.BSATN.String(); __memoryStream.Position = 0; __memoryStream.SetLength(0); value.Write(__writer, "A default string set by attribute"); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 1, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 1, array); } { @@ -3562,11 +4705,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, 2); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 10, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 10, array); } { @@ -3575,11 +4714,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, 2); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 11, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 11, array); } { @@ -3588,11 +4723,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, 2); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 12, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 12, array); } { @@ -3601,11 +4732,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, 2F); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 13, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 13, array); } { @@ -3614,11 +4741,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, 2); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 14, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 14, array); } { @@ -3627,11 +4750,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, (MyEnum)2); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 15, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 15, array); } { @@ -3640,11 +4759,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, null); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 16, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 16, array); } { @@ -3653,11 +4768,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, true); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 2, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 2, array); } { @@ -3666,11 +4777,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, 2); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 3, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 3, array); } { @@ -3679,11 +4786,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, 2); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 4, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 4, array); } { @@ -3692,11 +4795,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, 2); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 5, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 5, array); } { @@ -3705,11 +4804,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, 2); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 6, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 6, array); } { @@ -3718,11 +4813,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, 2); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 7, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 7, array); } { @@ -3731,11 +4822,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, 2); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 8, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 8, array); } { @@ -3744,11 +4831,7 @@ public static void Main() __memoryStream.SetLength(0); value.Write(__writer, 2); var array = __memoryStream.ToArray(); - SpacetimeDB.Internal.Module.RegisterTableDefaultValue( - "TestDefaultFieldValues", - 9, - array - ); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 9, array); } } @@ -4537,110 +5620,169 @@ public static SpacetimeDB.Internal.Errno __call_reducer__( SpacetimeDB.Timestamp timestamp, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink error + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ReducerCount + ) + return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalReducer( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ReducerCount; + return SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ); +#else + return CallLocalReducer( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error ) => id switch { - 0 - => __call_reducer_0( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - 1 - => __call_reducer_1( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - 2 - => __call_reducer_2( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - 3 - => __call_reducer_3( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - 4 - => __call_reducer_4( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - 5 - => __call_reducer_5( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - 6 - => __call_reducer_6( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - 7 - => __call_reducer_7( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - _ - => SpacetimeDB.Internal.Module.WriteReducerError( - error, - new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") - ) + 0 => __call_reducer_0( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 1 => __call_reducer_1( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 2 => __call_reducer_2( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 3 => __call_reducer_3( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 4 => __call_reducer_4( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 5 => __call_reducer_5( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 6 => __call_reducer_6( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 7 => __call_reducer_7( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + _ => SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ), }; #if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER @@ -4657,15 +5799,76 @@ public static SpacetimeDB.Internal.Errno __call_procedure__( SpacetimeDB.Timestamp timestamp, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink result_sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ProcedureCount + ) + return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalProcedure( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ProcedureCount; + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); +#else + return CallLocalProcedure( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink result_sink ) => id switch { - _ - => throw new System.ArgumentOutOfRangeException( - nameof(id), - id, - "Unknown procedure id" - ) + _ => throw new System.ArgumentOutOfRangeException( + nameof(id), + id, + "Unknown procedure id" + ), }; #if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER @@ -4678,15 +5881,64 @@ public static SpacetimeDB.Internal.Errno __call_http_handler__( SpacetimeDB.Internal.BytesSource request_body, SpacetimeDB.Internal.BytesSink response_sink, SpacetimeDB.Internal.BytesSink response_body_sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .HttpHandlerCount + ) + return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalHttpHandler( + localId, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .HttpHandlerCount; + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); +#else + return CallLocalHttpHandler( + id, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource request, + SpacetimeDB.Internal.BytesSource request_body, + SpacetimeDB.Internal.BytesSink response_sink, + SpacetimeDB.Internal.BytesSink response_body_sink ) => id switch { - _ - => throw new System.ArgumentOutOfRangeException( - nameof(id), - id, - "Unknown HTTP handler id" - ) + _ => throw new System.ArgumentOutOfRangeException( + nameof(id), + id, + "Unknown HTTP handler id" + ), }; #if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER @@ -4700,6 +5952,51 @@ public static SpacetimeDB.Internal.Errno __call_view__( ulong sender_3, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return UnknownViewId(id); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ViewCount + ) + return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalView( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + args, + sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ViewCount; + return UnknownViewId(id); +#else + return CallLocalView(id, sender_0, sender_1, sender_2, sender_3, args, sink); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink ) => id switch { @@ -4715,7 +6012,7 @@ SpacetimeDB.Internal.BytesSink sink 9 => __call_view_9(sender_0, sender_1, sender_2, sender_3, args, sink), 10 => __call_view_10(sender_0, sender_1, sender_2, sender_3, args, sink), 11 => __call_view_11(sender_0, sender_1, sender_2, sender_3, args, sink), - _ => UnknownViewId(id) + _ => UnknownViewId(id), }; #if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER @@ -4725,6 +6022,43 @@ public static SpacetimeDB.Internal.Errno __call_view_anon__( int id, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return UnknownAnonymousViewId(id); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .AnonymousViewCount + ) + return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalAnonymousView( + localId, + args, + sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .AnonymousViewCount; + return UnknownAnonymousViewId(id); +#else + return CallLocalAnonymousView(id, args, sink); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink ) => id switch { @@ -4732,7 +6066,7 @@ SpacetimeDB.Internal.BytesSink sink 1 => __call_view_anon_1(args, sink), 2 => __call_view_anon_2(args, sink), 3 => __call_view_anon_3(args, sink), - _ => UnknownAnonymousViewId(id) + _ => UnknownAnonymousViewId(id), }; private static SpacetimeDB.Internal.Errno UnknownViewId(int id) diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#Player.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#Player.verified.cs index ff392b76903..afcd60afc5b 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#Player.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#Player.verified.cs @@ -44,7 +44,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( new SpacetimeDB.BSATN.AggregateElement[] { - new("Identity", IdentityRW.GetAlgebraicType(registrar)) + new("Identity", IdentityRW.GetAlgebraicType(registrar)), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestAutoIncNotInteger.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestAutoIncNotInteger.verified.cs index 7efaa55cdcb..089c7521c72 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestAutoIncNotInteger.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestAutoIncNotInteger.verified.cs @@ -51,7 +51,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new SpacetimeDB.BSATN.AggregateElement[] { new("AutoIncField", AutoIncFieldRW.GetAlgebraicType(registrar)), - new("IdentityField", IdentityFieldRW.GetAlgebraicType(registrar)) + new("IdentityField", IdentityFieldRW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestDefaultFieldValues.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestDefaultFieldValues.verified.cs index de8c4cfdb03..bf5c8f0b4fc 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestDefaultFieldValues.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestDefaultFieldValues.verified.cs @@ -117,7 +117,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new("DefaultF32", DefaultF32RW.GetAlgebraicType(registrar)), new("DefaultF64", DefaultF64RW.GetAlgebraicType(registrar)), new("DefaultEnum", DefaultEnumRW.GetAlgebraicType(registrar)), - new("DefaultNull", DefaultNullRW.GetAlgebraicType(registrar)) + new("DefaultNull", DefaultNullRW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestIndexIssues.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestIndexIssues.verified.cs index 862805ded3e..3dd8a0a7425 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestIndexIssues.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestIndexIssues.verified.cs @@ -54,7 +54,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new( "SecondaryIndexingColumn", SecondaryIndexingColumnRW.GetAlgebraicType(registrar) - ) + ), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestScheduleIssues.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestScheduleIssues.verified.cs index 858ed058a53..cfbfc151870 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestScheduleIssues.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestScheduleIssues.verified.cs @@ -65,7 +65,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new( "ScheduleAtCorrectType", ScheduleAtCorrectTypeRW.GetAlgebraicType(registrar) - ) + ), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestTableTaggedEnum.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestTableTaggedEnum.verified.cs index 7e321681b88..38190b0b5f7 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestTableTaggedEnum.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestTableTaggedEnum.verified.cs @@ -27,10 +27,9 @@ public TestTableTaggedEnum Read(System.IO.BinaryReader reader) { 0 => new X(XRW.Read(reader)), 1 => new Y(YRW.Read(reader)), - _ - => throw new System.InvalidOperationException( - "Invalid tag value, this state should be unreachable." - ) + _ => throw new System.InvalidOperationException( + "Invalid tag value, this state should be unreachable." + ), }; } @@ -57,7 +56,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new SpacetimeDB.BSATN.AggregateElement[] { new("X", XRW.GetAlgebraicType(registrar)), - new("Y", YRW.GetAlgebraicType(registrar)) + new("Y", YRW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestUniqueNotEquatable.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestUniqueNotEquatable.verified.cs index 3c5ecbf67ff..c635f1a06ee 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestUniqueNotEquatable.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#TestUniqueNotEquatable.verified.cs @@ -55,7 +55,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new SpacetimeDB.BSATN.AggregateElement[] { new("UniqueField", UniqueFieldRW.GetAlgebraicType(registrar)), - new("PrimaryKeyField", PrimaryKeyFieldRW.GetAlgebraicType(registrar)) + new("PrimaryKeyField", PrimaryKeyFieldRW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs new file mode 100644 index 00000000000..c12c30f82aa --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs @@ -0,0 +1,6316 @@ +//HintName: FFI.cs +// +#nullable enable +// .NET 8 generates a module-local LocalReadOnly which shadows the runtime shell. +#pragma warning disable CS0436 +#pragma warning disable STDB_UNSTABLE + +#if NET10_0_OR_GREATER +global using SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C; +#endif +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Internal = SpacetimeDB.Internal; +using TxContext = SpacetimeDB.Internal.TxContext; +#if NET10_0_OR_GREATER +[assembly: global::SpacetimeDB.ModuleDescriptorAttribute( + typeof(global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor) +)] + +#endif + +namespace SpacetimeDB +{ +#if !NET10_0_OR_GREATER + public readonly struct TestDuplicateTableNameCols + { + internal TestDuplicateTableNameCols(string tableName) { } + } + + public readonly struct TestDuplicateTableNameIxCols + { + internal TestDuplicateTableNameIxCols(string tableName) { } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::InAnotherNamespace.TestDuplicateTableName, + TestDuplicateTableNameCols, + TestDuplicateTableNameIxCols + > TestDuplicateTableName() => + new( + "TestDuplicateTableName", + new TestDuplicateTableNameCols("TestDuplicateTableName"), + new TestDuplicateTableNameIxCols("TestDuplicateTableName") + ); + } + + public readonly struct PlayerCols + { + public readonly global::SpacetimeDB.Col Identity; + + internal PlayerCols(string tableName) + { + Identity = new global::SpacetimeDB.Col( + tableName, + "Identity" + ); + } + } + + public readonly struct PlayerIxCols + { + internal PlayerIxCols(string tableName) { } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table Player() => + new("Player", new PlayerCols("Player"), new PlayerIxCols("Player")); + } + + public readonly struct TestAutoIncNotIntegerCols + { + public readonly global::SpacetimeDB.Col AutoIncField; + public readonly global::SpacetimeDB.Col< + global::TestAutoIncNotInteger, + string + > IdentityField; + + internal TestAutoIncNotIntegerCols(string tableName) + { + AutoIncField = new global::SpacetimeDB.Col( + tableName, + "AutoIncField" + ); + IdentityField = new global::SpacetimeDB.Col( + tableName, + "IdentityField" + ); + } + } + + public readonly struct TestAutoIncNotIntegerIxCols + { + internal TestAutoIncNotIntegerIxCols(string tableName) { } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::TestAutoIncNotInteger, + TestAutoIncNotIntegerCols, + TestAutoIncNotIntegerIxCols + > TestAutoIncNotInteger() => + new( + "TestAutoIncNotInteger", + new TestAutoIncNotIntegerCols("TestAutoIncNotInteger"), + new TestAutoIncNotIntegerIxCols("TestAutoIncNotInteger") + ); + } + + public readonly struct TestDefaultFieldValuesCols + { + public readonly global::SpacetimeDB.Col UniqueField; + public readonly global::SpacetimeDB.Col< + global::TestDefaultFieldValues, + string + > DefaultString; + public readonly global::SpacetimeDB.Col DefaultBool; + public readonly global::SpacetimeDB.Col DefaultI8; + public readonly global::SpacetimeDB.Col DefaultU8; + public readonly global::SpacetimeDB.Col DefaultI16; + public readonly global::SpacetimeDB.Col DefaultU16; + public readonly global::SpacetimeDB.Col DefaultI32; + public readonly global::SpacetimeDB.Col DefaultU32; + public readonly global::SpacetimeDB.Col DefaultI64; + public readonly global::SpacetimeDB.Col DefaultU64; + public readonly global::SpacetimeDB.Col DefaultHex; + public readonly global::SpacetimeDB.Col DefaultBin; + public readonly global::SpacetimeDB.Col DefaultF32; + public readonly global::SpacetimeDB.Col DefaultF64; + public readonly global::SpacetimeDB.Col DefaultEnum; + public readonly global::SpacetimeDB.Col< + global::TestDefaultFieldValues, + MyStruct + > DefaultNull; + + internal TestDefaultFieldValuesCols(string tableName) + { + UniqueField = new global::SpacetimeDB.Col( + tableName, + "UniqueField" + ); + DefaultString = new global::SpacetimeDB.Col( + tableName, + "DefaultString" + ); + DefaultBool = new global::SpacetimeDB.Col( + tableName, + "DefaultBool" + ); + DefaultI8 = new global::SpacetimeDB.Col( + tableName, + "DefaultI8" + ); + DefaultU8 = new global::SpacetimeDB.Col( + tableName, + "DefaultU8" + ); + DefaultI16 = new global::SpacetimeDB.Col( + tableName, + "DefaultI16" + ); + DefaultU16 = new global::SpacetimeDB.Col( + tableName, + "DefaultU16" + ); + DefaultI32 = new global::SpacetimeDB.Col( + tableName, + "DefaultI32" + ); + DefaultU32 = new global::SpacetimeDB.Col( + tableName, + "DefaultU32" + ); + DefaultI64 = new global::SpacetimeDB.Col( + tableName, + "DefaultI64" + ); + DefaultU64 = new global::SpacetimeDB.Col( + tableName, + "DefaultU64" + ); + DefaultHex = new global::SpacetimeDB.Col( + tableName, + "DefaultHex" + ); + DefaultBin = new global::SpacetimeDB.Col( + tableName, + "DefaultBin" + ); + DefaultF32 = new global::SpacetimeDB.Col( + tableName, + "DefaultF32" + ); + DefaultF64 = new global::SpacetimeDB.Col( + tableName, + "DefaultF64" + ); + DefaultEnum = new global::SpacetimeDB.Col( + tableName, + "DefaultEnum" + ); + DefaultNull = new global::SpacetimeDB.Col( + tableName, + "DefaultNull" + ); + } + } + + public readonly struct TestDefaultFieldValuesIxCols + { + internal TestDefaultFieldValuesIxCols(string tableName) { } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::TestDefaultFieldValues, + TestDefaultFieldValuesCols, + TestDefaultFieldValuesIxCols + > TestDefaultFieldValues() => + new( + "TestDefaultFieldValues", + new TestDefaultFieldValuesCols("TestDefaultFieldValues"), + new TestDefaultFieldValuesIxCols("TestDefaultFieldValues") + ); + } + + public readonly struct TestDuplicateTableNameCols + { + internal TestDuplicateTableNameCols(string tableName) { } + } + + public readonly struct TestDuplicateTableNameIxCols + { + internal TestDuplicateTableNameIxCols(string tableName) { } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::TestDuplicateTableName, + TestDuplicateTableNameCols, + TestDuplicateTableNameIxCols + > TestDuplicateTableName() => + new( + "TestDuplicateTableName", + new TestDuplicateTableNameCols("TestDuplicateTableName"), + new TestDuplicateTableNameIxCols("TestDuplicateTableName") + ); + } + + public readonly struct TestIndexIssuesCols + { + public readonly global::SpacetimeDB.Col SelfIndexingColumn; + public readonly global::SpacetimeDB.Col< + global::TestIndexIssues, + int + > SecondaryIndexingColumn; + + internal TestIndexIssuesCols(string tableName) + { + SelfIndexingColumn = new global::SpacetimeDB.Col( + tableName, + "SelfIndexingColumn" + ); + SecondaryIndexingColumn = new global::SpacetimeDB.Col( + tableName, + "SecondaryIndexingColumn" + ); + } + } + + public readonly struct TestIndexIssuesIxCols + { + public readonly global::SpacetimeDB.IxCol SelfIndexingColumn; + public readonly global::SpacetimeDB.IxCol< + global::TestIndexIssues, + int + > SecondaryIndexingColumn; + + internal TestIndexIssuesIxCols(string tableName) + { + SelfIndexingColumn = new global::SpacetimeDB.IxCol( + tableName, + "SelfIndexingColumn" + ); + SecondaryIndexingColumn = new global::SpacetimeDB.IxCol( + tableName, + "SecondaryIndexingColumn" + ); + } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::TestIndexIssues, + TestIndexIssuesCols, + TestIndexIssuesIxCols + > TestIndexIssues() => + new( + "TestIndexIssues", + new TestIndexIssuesCols("TestIndexIssues"), + new TestIndexIssuesIxCols("TestIndexIssues") + ); + } + + public readonly struct TestScheduleWithoutPrimaryKeyCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithoutPrimaryKeyCols(string tableName) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithoutPrimaryKeyIxCols + { + internal TestScheduleWithoutPrimaryKeyIxCols(string tableName) { } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithoutPrimaryKeyCols, + TestScheduleWithoutPrimaryKeyIxCols + > TestScheduleWithoutPrimaryKey() => + new( + "TestScheduleWithoutPrimaryKey", + new TestScheduleWithoutPrimaryKeyCols("TestScheduleWithoutPrimaryKey"), + new TestScheduleWithoutPrimaryKeyIxCols("TestScheduleWithoutPrimaryKey") + ); + } + + public readonly struct TestScheduleWithWrongPrimaryKeyTypeCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithWrongPrimaryKeyTypeCols(string tableName) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithWrongPrimaryKeyTypeIxCols + { + public readonly global::SpacetimeDB.IxCol IdWrongType; + + internal TestScheduleWithWrongPrimaryKeyTypeIxCols(string tableName) + { + IdWrongType = new global::SpacetimeDB.IxCol( + tableName, + "IdWrongType" + ); + } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithWrongPrimaryKeyTypeCols, + TestScheduleWithWrongPrimaryKeyTypeIxCols + > TestScheduleWithWrongPrimaryKeyType() => + new( + "TestScheduleWithWrongPrimaryKeyType", + new TestScheduleWithWrongPrimaryKeyTypeCols("TestScheduleWithWrongPrimaryKeyType"), + new TestScheduleWithWrongPrimaryKeyTypeIxCols("TestScheduleWithWrongPrimaryKeyType") + ); + } + + public readonly struct TestScheduleWithoutScheduleAtCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithoutScheduleAtCols(string tableName) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithoutScheduleAtIxCols + { + public readonly global::SpacetimeDB.IxCol IdCorrectType; + + internal TestScheduleWithoutScheduleAtIxCols(string tableName) + { + IdCorrectType = new global::SpacetimeDB.IxCol( + tableName, + "IdCorrectType" + ); + } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithoutScheduleAtCols, + TestScheduleWithoutScheduleAtIxCols + > TestScheduleWithoutScheduleAt() => + new( + "TestScheduleWithoutScheduleAt", + new TestScheduleWithoutScheduleAtCols("TestScheduleWithoutScheduleAt"), + new TestScheduleWithoutScheduleAtIxCols("TestScheduleWithoutScheduleAt") + ); + } + + public readonly struct TestScheduleWithWrongScheduleAtTypeCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithWrongScheduleAtTypeCols(string tableName) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithWrongScheduleAtTypeIxCols + { + public readonly global::SpacetimeDB.IxCol IdCorrectType; + + internal TestScheduleWithWrongScheduleAtTypeIxCols(string tableName) + { + IdCorrectType = new global::SpacetimeDB.IxCol( + tableName, + "IdCorrectType" + ); + } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithWrongScheduleAtTypeCols, + TestScheduleWithWrongScheduleAtTypeIxCols + > TestScheduleWithWrongScheduleAtType() => + new( + "TestScheduleWithWrongScheduleAtType", + new TestScheduleWithWrongScheduleAtTypeCols("TestScheduleWithWrongScheduleAtType"), + new TestScheduleWithWrongScheduleAtTypeIxCols("TestScheduleWithWrongScheduleAtType") + ); + } + + public readonly struct TestScheduleWithMissingScheduleAtFieldCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithMissingScheduleAtFieldCols(string tableName) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithMissingScheduleAtFieldIxCols + { + internal TestScheduleWithMissingScheduleAtFieldIxCols(string tableName) { } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithMissingScheduleAtFieldCols, + TestScheduleWithMissingScheduleAtFieldIxCols + > TestScheduleWithMissingScheduleAtField() => + new( + "TestScheduleWithMissingScheduleAtField", + new TestScheduleWithMissingScheduleAtFieldCols( + "TestScheduleWithMissingScheduleAtField" + ), + new TestScheduleWithMissingScheduleAtFieldIxCols( + "TestScheduleWithMissingScheduleAtField" + ) + ); + } + + public readonly struct TestUniqueNotEquatableCols + { + public readonly global::SpacetimeDB.Col UniqueField; + public readonly global::SpacetimeDB.Col< + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues + > PrimaryKeyField; + + internal TestUniqueNotEquatableCols(string tableName) + { + UniqueField = new global::SpacetimeDB.Col( + tableName, + "UniqueField" + ); + PrimaryKeyField = new global::SpacetimeDB.Col< + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues + >(tableName, "PrimaryKeyField"); + } + } + + public readonly struct TestUniqueNotEquatableIxCols + { + public readonly global::SpacetimeDB.IxCol< + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues + > PrimaryKeyField; + + internal TestUniqueNotEquatableIxCols(string tableName) + { + PrimaryKeyField = new global::SpacetimeDB.IxCol< + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues + >(tableName, "PrimaryKeyField"); + } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::TestUniqueNotEquatable, + TestUniqueNotEquatableCols, + TestUniqueNotEquatableIxCols + > TestUniqueNotEquatable() => + new( + "TestUniqueNotEquatable", + new TestUniqueNotEquatableCols("TestUniqueNotEquatable"), + new TestUniqueNotEquatableIxCols("TestUniqueNotEquatable") + ); + } +#endif + + public static class Handlers { } + +#if !NET10_0_OR_GREATER + public sealed record ReducerContext : DbContext, Internal.IReducerContext + { + public readonly Identity Sender; + public readonly ConnectionId? ConnectionId; + public readonly Random Rng; + public readonly Timestamp Timestamp; + public readonly AuthCtx SenderAuth; + + // **Note:** must be 0..=u32::MAX + internal int CounterUuid; + public Identity DatabaseIdentity => Internal.IReducerContext.GetDatabaseIdentity(); + + // We keep this property for compatibility with existing module code. + [global::System.Obsolete( + "ReducerContext.Identity is deprecated. Use DatabaseIdentity instead." + )] + public Identity Identity => DatabaseIdentity; + + internal ReducerContext( + Identity identity, + ConnectionId? connectionId, + Random random, + Timestamp time, + AuthCtx? senderAuth = null + ) + { + Sender = identity; + ConnectionId = connectionId; + Rng = random; + Timestamp = time; + SenderAuth = senderAuth ?? AuthCtx.BuildFromSystemTables(connectionId, identity); + CounterUuid = 0; + } + + /// + /// Create a new random `v4` using the built-in RNG. + /// + /// + /// This method fills the random bytes using the context RNG. + /// + /// + /// + /// var uuid = ctx.NewUuidV4(); + /// Log.Info(uuid); + /// + /// + public Uuid NewUuidV4() + { + var bytes = new byte[16]; + Rng.NextBytes(bytes); + return Uuid.FromRandomBytesV4(bytes); + } + + /// + /// Create a new sortable `v7` using the built-in RNG, monotonic counter, + /// and timestamp. + /// + /// + /// A newly generated `v7` that is monotonically ordered + /// and suitable for use as a primary key or for ordered storage. + /// + /// + /// Thrown if generation fails. + /// + /// + /// + /// [SpacetimeDB.Reducer] + /// public static Guid GenerateUuidV7(ReducerContext ctx) + /// { + /// Guid uuid = ctx.NewUuidV7(); + /// Log.Info(uuid); + /// } + /// + /// + public Uuid NewUuidV7() + { + var bytes = new byte[4]; + Rng.NextBytes(bytes); + return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); + } + } + + public sealed partial class ProcedureContext : global::SpacetimeDB.ProcedureContextBase + { + private readonly Local _db = new(); + + internal ProcedureContext( + Identity identity, + ConnectionId? connectionId, + Random random, + Timestamp time + ) + : base(identity, connectionId, random, time) { } + + protected override global::SpacetimeDB.LocalBase CreateLocal() => _db; + + protected override global::SpacetimeDB.ProcedureTxContextBase CreateTxContext( + Internal.TxContext inner + ) => _cached ??= new ProcedureTxContext(inner); + + private ProcedureTxContext? _cached; + + public Local Db => _db; + + public TResult WithTx(Func body) => + base.WithTx(tx => body((ProcedureTxContext)tx)); + + public TxOutcome TryWithTx( + Func> body + ) + where TError : Exception => base.TryWithTx(tx => body((ProcedureTxContext)tx)); + + /// + /// Create a new random `v4` using the built-in RNG. + /// + /// + /// This method fills the random bytes using the context RNG. + /// + /// + /// + /// var uuid = ctx.NewUuidV4(); + /// Log.Info(uuid); + /// + /// + public Uuid NewUuidV4() + { + var bytes = new byte[16]; + Rng.NextBytes(bytes); + return Uuid.FromRandomBytesV4(bytes); + } + + /// + /// Create a new sortable `v7` using the built-in RNG, monotonic counter, + /// and timestamp. + /// + /// + /// A newly generated `v7` that is monotonically ordered + /// and suitable for use as a primary key or for ordered storage. + /// + /// + /// Thrown if UUID generation fails. + /// + /// + /// + /// [SpacetimeDB.Procedure] + /// public static Guid GenerateUuidV7(ReducerContext ctx) + /// { + /// Guid uuid = ctx.NewUuidV7(); + /// Log.Info(uuid); + /// } + /// + /// + public Uuid NewUuidV7() + { + var bytes = new byte[4]; + Rng.NextBytes(bytes); + return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); + } + } + + public sealed partial class HandlerContext : global::SpacetimeDB.HandlerContextBase + { + private readonly Local _db = new(); + + internal HandlerContext(Random random, Timestamp time) + : base(random, time) { } + + protected override global::SpacetimeDB.LocalBase CreateLocal() => _db; + + protected override global::SpacetimeDB.HandlerTxContextBase CreateTxContext( + Internal.TxContext inner + ) => _cached ??= new HandlerTxContext(inner); + + private HandlerTxContext? _cached; + + [Experimental("STDB_UNSTABLE")] + public TResult WithTx(Func body) => + base.WithTx(tx => body((HandlerTxContext)tx)); + + [Experimental("STDB_UNSTABLE")] + public TxOutcome TryWithTx( + Func> body + ) + where TError : Exception => base.TryWithTx(tx => body((HandlerTxContext)tx)); + + public Uuid NewUuidV4() + { + var bytes = new byte[16]; + Rng.NextBytes(bytes); + return Uuid.FromRandomBytesV4(bytes); + } + + public Uuid NewUuidV7() + { + var bytes = new byte[4]; + Rng.NextBytes(bytes); + return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); + } + } + + public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase + { + internal ProcedureTxContext(Internal.TxContext inner) + : base(inner) { } + + public new Local Db => (Local)base.Db; + } + + [Experimental("STDB_UNSTABLE")] + public sealed class HandlerTxContext : global::SpacetimeDB.HandlerTxContextBase + { + internal HandlerTxContext(Internal.TxContext inner) + : base(inner) { } + + public new Local Db => (Local)base.Db; + } + + public sealed class Local : global::SpacetimeDB.LocalBase + { + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.Player Player => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestAutoIncNotInteger TestAutoIncNotInteger => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDefaultFieldValues TestDefaultFieldValues => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDuplicateTableName TestDuplicateTableName => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestIndexIssues TestIndexIssues => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithMissingScheduleAtField TestScheduleWithMissingScheduleAtField => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutPrimaryKey TestScheduleWithoutPrimaryKey => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutScheduleAt TestScheduleWithoutScheduleAt => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongPrimaryKeyType TestScheduleWithWrongPrimaryKeyType => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongScheduleAtType TestScheduleWithWrongScheduleAtType => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestUniqueNotEquatable TestUniqueNotEquatable => + new(); + } + + public sealed record ViewContext : DbContext, Internal.IViewContext + { + public Identity Sender { get; } + + public QueryBuilder From => default; + + internal ViewContext(Identity sender, Internal.LocalReadOnly db) + : base(db) + { + Sender = sender; + } + } + + public sealed record AnonymousViewContext + : DbContext, + Internal.IAnonymousViewContext + { + public QueryBuilder From => default; + + internal AnonymousViewContext(Internal.LocalReadOnly db) + : base(db) { } + } +#endif +} + +#if NET10_0_OR_GREATER +namespace SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +{ + public static partial class AssemblyDescriptor + { + public const string LifecycleReducers = + "Reducers.TestDuplicateReducerKind1 (Init), Reducers.TestDuplicateReducerKind2 (Init)"; + public const int ReducerCount = 8; + public const int ProcedureCount = 0; + public const int HttpHandlerCount = 0; + public const int ViewCount = 12; + public const int AnonymousViewCount = 4; + + public static global::SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink error + ) => + global::ModuleRegistration.CallLocalReducer( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink result_sink + ) => + global::ModuleRegistration.CallLocalProcedure( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource request, + global::SpacetimeDB.Internal.BytesSource request_body, + global::SpacetimeDB.Internal.BytesSink response_sink, + global::SpacetimeDB.Internal.BytesSink response_body_sink + ) => + global::ModuleRegistration.CallLocalHttpHandler( + id, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => + global::ModuleRegistration.CallLocalView( + id, + sender_0, + sender_1, + sender_2, + sender_3, + args, + sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => global::ModuleRegistration.CallLocalAnonymousView(id, args, sink); + + public static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null + ) => global::ModuleRegistration.Register(builder, httpBuilder); + + public readonly struct Tables + { + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.Player Player => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestAutoIncNotInteger TestAutoIncNotInteger => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDefaultFieldValues TestDefaultFieldValues => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDuplicateTableName TestDuplicateTableName => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestIndexIssues TestIndexIssues => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithMissingScheduleAtField TestScheduleWithMissingScheduleAtField => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutPrimaryKey TestScheduleWithoutPrimaryKey => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutScheduleAt TestScheduleWithoutScheduleAt => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongPrimaryKeyType TestScheduleWithWrongPrimaryKeyType => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongScheduleAtType TestScheduleWithWrongScheduleAtType => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestUniqueNotEquatable TestUniqueNotEquatable => + new(); + } + + public readonly struct ReadOnlyTables + { + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PlayerReadOnly Player => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestAutoIncNotIntegerReadOnly TestAutoIncNotInteger => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestDefaultFieldValuesReadOnly TestDefaultFieldValues => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestDuplicateTableNameReadOnly TestDuplicateTableName => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestIndexIssuesReadOnly TestIndexIssues => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithMissingScheduleAtFieldReadOnly TestScheduleWithMissingScheduleAtField => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutPrimaryKeyReadOnly TestScheduleWithoutPrimaryKey => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutScheduleAtReadOnly TestScheduleWithoutScheduleAt => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly TestScheduleWithWrongPrimaryKeyType => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly TestScheduleWithWrongScheduleAtType => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestUniqueNotEquatableReadOnly TestUniqueNotEquatable => + new(); + } + + public readonly partial struct Queries { } + } + + public static class LocalTableExtensions + { + extension(global::SpacetimeDB.Local db) + { + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.Player Player => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestAutoIncNotInteger TestAutoIncNotInteger => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDefaultFieldValues TestDefaultFieldValues => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDuplicateTableName TestDuplicateTableName => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestIndexIssues TestIndexIssues => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithMissingScheduleAtField TestScheduleWithMissingScheduleAtField => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutPrimaryKey TestScheduleWithoutPrimaryKey => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutScheduleAt TestScheduleWithoutScheduleAt => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongPrimaryKeyType TestScheduleWithWrongPrimaryKeyType => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongScheduleAtType TestScheduleWithWrongScheduleAtType => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestUniqueNotEquatable TestUniqueNotEquatable => + new(); + } + } + + public static class ReadOnlyTableExtensions + { + extension(global::SpacetimeDB.Internal.LocalReadOnly db) + { + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PlayerReadOnly Player => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestAutoIncNotIntegerReadOnly TestAutoIncNotInteger => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestDefaultFieldValuesReadOnly TestDefaultFieldValues => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestDuplicateTableNameReadOnly TestDuplicateTableName => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestIndexIssuesReadOnly TestIndexIssues => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithMissingScheduleAtFieldReadOnly TestScheduleWithMissingScheduleAtField => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutPrimaryKeyReadOnly TestScheduleWithoutPrimaryKey => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutScheduleAtReadOnly TestScheduleWithoutScheduleAt => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly TestScheduleWithWrongPrimaryKeyType => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly TestScheduleWithWrongScheduleAtType => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestUniqueNotEquatableReadOnly TestUniqueNotEquatable => + new(); + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) { } + } + + public readonly struct TestDuplicateTableNameCols + { + internal TestDuplicateTableNameCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public readonly struct TestDuplicateTableNameIxCols + { + internal TestDuplicateTableNameIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::InAnotherNamespace.TestDuplicateTableName, + TestDuplicateTableNameCols, + TestDuplicateTableNameIxCols + > TestDuplicateTableName() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDuplicateTableName" + ); + return new( + tableName, + new TestDuplicateTableNameCols(tableName), + new TestDuplicateTableNameIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::InAnotherNamespace.TestDuplicateTableName, + TestDuplicateTableNameCols, + TestDuplicateTableNameIxCols + > TestDuplicateTableName() => new AssemblyDescriptor.Queries().TestDuplicateTableName(); + } + } + + public readonly struct PlayerCols + { + public readonly global::SpacetimeDB.Col Identity; + + internal PlayerCols(global::SpacetimeDB.SqlTableName tableName) + { + Identity = new global::SpacetimeDB.Col( + tableName, + "Identity" + ); + } + } + + public readonly struct PlayerIxCols + { + internal PlayerIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table Player() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "Player" + ); + return new(tableName, new PlayerCols(tableName), new PlayerIxCols(tableName)); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table Player() => + new AssemblyDescriptor.Queries().Player(); + } + } + + public readonly struct TestAutoIncNotIntegerCols + { + public readonly global::SpacetimeDB.Col AutoIncField; + public readonly global::SpacetimeDB.Col< + global::TestAutoIncNotInteger, + string + > IdentityField; + + internal TestAutoIncNotIntegerCols(global::SpacetimeDB.SqlTableName tableName) + { + AutoIncField = new global::SpacetimeDB.Col( + tableName, + "AutoIncField" + ); + IdentityField = new global::SpacetimeDB.Col( + tableName, + "IdentityField" + ); + } + } + + public readonly struct TestAutoIncNotIntegerIxCols + { + internal TestAutoIncNotIntegerIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestAutoIncNotInteger, + TestAutoIncNotIntegerCols, + TestAutoIncNotIntegerIxCols + > TestAutoIncNotInteger() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestAutoIncNotInteger" + ); + return new( + tableName, + new TestAutoIncNotIntegerCols(tableName), + new TestAutoIncNotIntegerIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestAutoIncNotInteger, + TestAutoIncNotIntegerCols, + TestAutoIncNotIntegerIxCols + > TestAutoIncNotInteger() => new AssemblyDescriptor.Queries().TestAutoIncNotInteger(); + } + } + + public readonly struct TestDefaultFieldValuesCols + { + public readonly global::SpacetimeDB.Col UniqueField; + public readonly global::SpacetimeDB.Col< + global::TestDefaultFieldValues, + string + > DefaultString; + public readonly global::SpacetimeDB.Col DefaultBool; + public readonly global::SpacetimeDB.Col DefaultI8; + public readonly global::SpacetimeDB.Col DefaultU8; + public readonly global::SpacetimeDB.Col DefaultI16; + public readonly global::SpacetimeDB.Col DefaultU16; + public readonly global::SpacetimeDB.Col DefaultI32; + public readonly global::SpacetimeDB.Col DefaultU32; + public readonly global::SpacetimeDB.Col DefaultI64; + public readonly global::SpacetimeDB.Col DefaultU64; + public readonly global::SpacetimeDB.Col DefaultHex; + public readonly global::SpacetimeDB.Col DefaultBin; + public readonly global::SpacetimeDB.Col DefaultF32; + public readonly global::SpacetimeDB.Col DefaultF64; + public readonly global::SpacetimeDB.Col DefaultEnum; + public readonly global::SpacetimeDB.Col< + global::TestDefaultFieldValues, + MyStruct + > DefaultNull; + + internal TestDefaultFieldValuesCols(global::SpacetimeDB.SqlTableName tableName) + { + UniqueField = new global::SpacetimeDB.Col( + tableName, + "UniqueField" + ); + DefaultString = new global::SpacetimeDB.Col( + tableName, + "DefaultString" + ); + DefaultBool = new global::SpacetimeDB.Col( + tableName, + "DefaultBool" + ); + DefaultI8 = new global::SpacetimeDB.Col( + tableName, + "DefaultI8" + ); + DefaultU8 = new global::SpacetimeDB.Col( + tableName, + "DefaultU8" + ); + DefaultI16 = new global::SpacetimeDB.Col( + tableName, + "DefaultI16" + ); + DefaultU16 = new global::SpacetimeDB.Col( + tableName, + "DefaultU16" + ); + DefaultI32 = new global::SpacetimeDB.Col( + tableName, + "DefaultI32" + ); + DefaultU32 = new global::SpacetimeDB.Col( + tableName, + "DefaultU32" + ); + DefaultI64 = new global::SpacetimeDB.Col( + tableName, + "DefaultI64" + ); + DefaultU64 = new global::SpacetimeDB.Col( + tableName, + "DefaultU64" + ); + DefaultHex = new global::SpacetimeDB.Col( + tableName, + "DefaultHex" + ); + DefaultBin = new global::SpacetimeDB.Col( + tableName, + "DefaultBin" + ); + DefaultF32 = new global::SpacetimeDB.Col( + tableName, + "DefaultF32" + ); + DefaultF64 = new global::SpacetimeDB.Col( + tableName, + "DefaultF64" + ); + DefaultEnum = new global::SpacetimeDB.Col( + tableName, + "DefaultEnum" + ); + DefaultNull = new global::SpacetimeDB.Col( + tableName, + "DefaultNull" + ); + } + } + + public readonly struct TestDefaultFieldValuesIxCols + { + internal TestDefaultFieldValuesIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestDefaultFieldValues, + TestDefaultFieldValuesCols, + TestDefaultFieldValuesIxCols + > TestDefaultFieldValues() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDefaultFieldValues" + ); + return new( + tableName, + new TestDefaultFieldValuesCols(tableName), + new TestDefaultFieldValuesIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestDefaultFieldValues, + TestDefaultFieldValuesCols, + TestDefaultFieldValuesIxCols + > TestDefaultFieldValues() => new AssemblyDescriptor.Queries().TestDefaultFieldValues(); + } + } + + public readonly struct TestDuplicateTableNameCols + { + internal TestDuplicateTableNameCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public readonly struct TestDuplicateTableNameIxCols + { + internal TestDuplicateTableNameIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestDuplicateTableName, + TestDuplicateTableNameCols, + TestDuplicateTableNameIxCols + > TestDuplicateTableName() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDuplicateTableName" + ); + return new( + tableName, + new TestDuplicateTableNameCols(tableName), + new TestDuplicateTableNameIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestDuplicateTableName, + TestDuplicateTableNameCols, + TestDuplicateTableNameIxCols + > TestDuplicateTableName() => new AssemblyDescriptor.Queries().TestDuplicateTableName(); + } + } + + public readonly struct TestIndexIssuesCols + { + public readonly global::SpacetimeDB.Col SelfIndexingColumn; + public readonly global::SpacetimeDB.Col< + global::TestIndexIssues, + int + > SecondaryIndexingColumn; + + internal TestIndexIssuesCols(global::SpacetimeDB.SqlTableName tableName) + { + SelfIndexingColumn = new global::SpacetimeDB.Col( + tableName, + "SelfIndexingColumn" + ); + SecondaryIndexingColumn = new global::SpacetimeDB.Col( + tableName, + "SecondaryIndexingColumn" + ); + } + } + + public readonly struct TestIndexIssuesIxCols + { + public readonly global::SpacetimeDB.IxCol SelfIndexingColumn; + public readonly global::SpacetimeDB.IxCol< + global::TestIndexIssues, + int + > SecondaryIndexingColumn; + + internal TestIndexIssuesIxCols(global::SpacetimeDB.SqlTableName tableName) + { + SelfIndexingColumn = new global::SpacetimeDB.IxCol( + tableName, + "SelfIndexingColumn" + ); + SecondaryIndexingColumn = new global::SpacetimeDB.IxCol( + tableName, + "SecondaryIndexingColumn" + ); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestIndexIssues, + TestIndexIssuesCols, + TestIndexIssuesIxCols + > TestIndexIssues() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues" + ); + return new( + tableName, + new TestIndexIssuesCols(tableName), + new TestIndexIssuesIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestIndexIssues, + TestIndexIssuesCols, + TestIndexIssuesIxCols + > TestIndexIssues() => new AssemblyDescriptor.Queries().TestIndexIssues(); + } + } + + public readonly struct TestScheduleWithoutPrimaryKeyCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithoutPrimaryKeyCols(global::SpacetimeDB.SqlTableName tableName) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithoutPrimaryKeyIxCols + { + internal TestScheduleWithoutPrimaryKeyIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithoutPrimaryKeyCols, + TestScheduleWithoutPrimaryKeyIxCols + > TestScheduleWithoutPrimaryKey() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutPrimaryKey" + ); + return new( + tableName, + new TestScheduleWithoutPrimaryKeyCols(tableName), + new TestScheduleWithoutPrimaryKeyIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithoutPrimaryKeyCols, + TestScheduleWithoutPrimaryKeyIxCols + > TestScheduleWithoutPrimaryKey() => + new AssemblyDescriptor.Queries().TestScheduleWithoutPrimaryKey(); + } + } + + public readonly struct TestScheduleWithWrongPrimaryKeyTypeCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithWrongPrimaryKeyTypeCols(global::SpacetimeDB.SqlTableName tableName) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithWrongPrimaryKeyTypeIxCols + { + public readonly global::SpacetimeDB.IxCol IdWrongType; + + internal TestScheduleWithWrongPrimaryKeyTypeIxCols( + global::SpacetimeDB.SqlTableName tableName + ) + { + IdWrongType = new global::SpacetimeDB.IxCol( + tableName, + "IdWrongType" + ); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithWrongPrimaryKeyTypeCols, + TestScheduleWithWrongPrimaryKeyTypeIxCols + > TestScheduleWithWrongPrimaryKeyType() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongPrimaryKeyType" + ); + return new( + tableName, + new TestScheduleWithWrongPrimaryKeyTypeCols(tableName), + new TestScheduleWithWrongPrimaryKeyTypeIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithWrongPrimaryKeyTypeCols, + TestScheduleWithWrongPrimaryKeyTypeIxCols + > TestScheduleWithWrongPrimaryKeyType() => + new AssemblyDescriptor.Queries().TestScheduleWithWrongPrimaryKeyType(); + } + } + + public readonly struct TestScheduleWithoutScheduleAtCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithoutScheduleAtCols(global::SpacetimeDB.SqlTableName tableName) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithoutScheduleAtIxCols + { + public readonly global::SpacetimeDB.IxCol IdCorrectType; + + internal TestScheduleWithoutScheduleAtIxCols(global::SpacetimeDB.SqlTableName tableName) + { + IdCorrectType = new global::SpacetimeDB.IxCol( + tableName, + "IdCorrectType" + ); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithoutScheduleAtCols, + TestScheduleWithoutScheduleAtIxCols + > TestScheduleWithoutScheduleAt() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutScheduleAt" + ); + return new( + tableName, + new TestScheduleWithoutScheduleAtCols(tableName), + new TestScheduleWithoutScheduleAtIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithoutScheduleAtCols, + TestScheduleWithoutScheduleAtIxCols + > TestScheduleWithoutScheduleAt() => + new AssemblyDescriptor.Queries().TestScheduleWithoutScheduleAt(); + } + } + + public readonly struct TestScheduleWithWrongScheduleAtTypeCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithWrongScheduleAtTypeCols(global::SpacetimeDB.SqlTableName tableName) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithWrongScheduleAtTypeIxCols + { + public readonly global::SpacetimeDB.IxCol IdCorrectType; + + internal TestScheduleWithWrongScheduleAtTypeIxCols( + global::SpacetimeDB.SqlTableName tableName + ) + { + IdCorrectType = new global::SpacetimeDB.IxCol( + tableName, + "IdCorrectType" + ); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithWrongScheduleAtTypeCols, + TestScheduleWithWrongScheduleAtTypeIxCols + > TestScheduleWithWrongScheduleAtType() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongScheduleAtType" + ); + return new( + tableName, + new TestScheduleWithWrongScheduleAtTypeCols(tableName), + new TestScheduleWithWrongScheduleAtTypeIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithWrongScheduleAtTypeCols, + TestScheduleWithWrongScheduleAtTypeIxCols + > TestScheduleWithWrongScheduleAtType() => + new AssemblyDescriptor.Queries().TestScheduleWithWrongScheduleAtType(); + } + } + + public readonly struct TestScheduleWithMissingScheduleAtFieldCols + { + public readonly global::SpacetimeDB.Col IdWrongType; + public readonly global::SpacetimeDB.Col IdCorrectType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + int + > ScheduleAtWrongType; + public readonly global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + > ScheduleAtCorrectType; + + internal TestScheduleWithMissingScheduleAtFieldCols( + global::SpacetimeDB.SqlTableName tableName + ) + { + IdWrongType = new global::SpacetimeDB.Col( + tableName, + "IdWrongType" + ); + IdCorrectType = new global::SpacetimeDB.Col( + tableName, + "IdCorrectType" + ); + ScheduleAtWrongType = new global::SpacetimeDB.Col( + tableName, + "ScheduleAtWrongType" + ); + ScheduleAtCorrectType = new global::SpacetimeDB.Col< + global::TestScheduleIssues, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduleAtCorrectType"); + } + } + + public readonly struct TestScheduleWithMissingScheduleAtFieldIxCols + { + internal TestScheduleWithMissingScheduleAtFieldIxCols( + global::SpacetimeDB.SqlTableName tableName + ) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithMissingScheduleAtFieldCols, + TestScheduleWithMissingScheduleAtFieldIxCols + > TestScheduleWithMissingScheduleAtField() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithMissingScheduleAtField" + ); + return new( + tableName, + new TestScheduleWithMissingScheduleAtFieldCols(tableName), + new TestScheduleWithMissingScheduleAtFieldIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestScheduleIssues, + TestScheduleWithMissingScheduleAtFieldCols, + TestScheduleWithMissingScheduleAtFieldIxCols + > TestScheduleWithMissingScheduleAtField() => + new AssemblyDescriptor.Queries().TestScheduleWithMissingScheduleAtField(); + } + } + + public readonly struct TestUniqueNotEquatableCols + { + public readonly global::SpacetimeDB.Col UniqueField; + public readonly global::SpacetimeDB.Col< + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues + > PrimaryKeyField; + + internal TestUniqueNotEquatableCols(global::SpacetimeDB.SqlTableName tableName) + { + UniqueField = new global::SpacetimeDB.Col( + tableName, + "UniqueField" + ); + PrimaryKeyField = new global::SpacetimeDB.Col< + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues + >(tableName, "PrimaryKeyField"); + } + } + + public readonly struct TestUniqueNotEquatableIxCols + { + public readonly global::SpacetimeDB.IxCol< + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues + > PrimaryKeyField; + + internal TestUniqueNotEquatableIxCols(global::SpacetimeDB.SqlTableName tableName) + { + PrimaryKeyField = new global::SpacetimeDB.IxCol< + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues + >(tableName, "PrimaryKeyField"); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::TestUniqueNotEquatable, + TestUniqueNotEquatableCols, + TestUniqueNotEquatableIxCols + > TestUniqueNotEquatable() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestUniqueNotEquatable" + ); + return new( + tableName, + new TestUniqueNotEquatableCols(tableName), + new TestUniqueNotEquatableIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::TestUniqueNotEquatable, + TestUniqueNotEquatableCols, + TestUniqueNotEquatableIxCols + > TestUniqueNotEquatable() => new AssemblyDescriptor.Queries().TestUniqueNotEquatable(); + } + } +} +#endif + +namespace SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles +{ + public readonly struct Player : global::SpacetimeDB.Internal.ITableView + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "Player" + ); + + public static global::Player ReadGenFields( + System.IO.BinaryReader reader, + global::Player row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(Player), + ProductTypeRef: (uint)new global::Player.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: + [ + new( + SourceName: "Player_Identity_idx_btree", + AccessorName: "Identity", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + Player, + global::Player + >.MakeUniqueConstraint(0), + ], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView.DoIter(); + + public global::Player Insert(global::Player row) => + global::SpacetimeDB.Internal.ITableView.DoInsert(row); + + public bool Delete(global::Player row) => + global::SpacetimeDB.Internal.ITableView.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView.DoClear(); + + public sealed class IdentityUniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + Player, + global::Player, + SpacetimeDB.Identity, + SpacetimeDB.Identity.BSATN + > + { + internal IdentityUniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "Player_Identity_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::Player? Find(SpacetimeDB.Identity key) => FindSingle(key); + } + + public IdentityUniqueIndex Identity => new(); + } + + public readonly struct TestAutoIncNotInteger + : global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + > + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestAutoIncNotInteger" + ); + + public static global::TestAutoIncNotInteger ReadGenFields( + System.IO.BinaryReader reader, + global::TestAutoIncNotInteger row + ) + { + if (row.AutoIncField == default) + { + row.AutoIncField = global::TestAutoIncNotInteger.BSATN.AutoIncFieldRW.Read(reader); + } + if (row.IdentityField == default) + { + row.IdentityField = global::TestAutoIncNotInteger.BSATN.IdentityFieldRW.Read( + reader + ); + } + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestAutoIncNotInteger), + ProductTypeRef: (uint) + new global::TestAutoIncNotInteger.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: + [ + new( + SourceName: "TestAutoIncNotInteger_IdentityField_idx_btree", + AccessorName: "IdentityField", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.MakeUniqueConstraint(1), + ], + Sequences: + [ + global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.MakeSequence(0), + global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.MakeSequence(1), + ], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.DoIter(); + + public global::TestAutoIncNotInteger Insert(global::TestAutoIncNotInteger row) => + global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.DoInsert(row); + + public bool Delete(global::TestAutoIncNotInteger row) => + global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.DoClear(); + + public sealed class IdentityFieldUniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger, + string, + SpacetimeDB.BSATN.String + > + { + internal IdentityFieldUniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestAutoIncNotInteger_IdentityField_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::TestAutoIncNotInteger? Find(string key) => FindSingle(key); + } + + public IdentityFieldUniqueIndex IdentityField => new(); + } + + public readonly struct TestDefaultFieldValues + : global::SpacetimeDB.Internal.ITableView< + TestDefaultFieldValues, + global::TestDefaultFieldValues + > + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDefaultFieldValues" + ); + + public static global::TestDefaultFieldValues ReadGenFields( + System.IO.BinaryReader reader, + global::TestDefaultFieldValues row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestDefaultFieldValues), + ProductTypeRef: (uint) + new global::TestDefaultFieldValues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: + [ + new( + SourceName: "TestDefaultFieldValues_UniqueField_idx_btree", + AccessorName: "UniqueField", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + TestDefaultFieldValues, + global::TestDefaultFieldValues + >.MakeUniqueConstraint(0), + ], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + TestDefaultFieldValues, + global::TestDefaultFieldValues + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + TestDefaultFieldValues, + global::TestDefaultFieldValues + >.DoIter(); + + public global::TestDefaultFieldValues Insert(global::TestDefaultFieldValues row) => + global::SpacetimeDB.Internal.ITableView< + TestDefaultFieldValues, + global::TestDefaultFieldValues + >.DoInsert(row); + + public bool Delete(global::TestDefaultFieldValues row) => + global::SpacetimeDB.Internal.ITableView< + TestDefaultFieldValues, + global::TestDefaultFieldValues + >.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView< + TestDefaultFieldValues, + global::TestDefaultFieldValues + >.DoClear(); + } + + public readonly struct TestDuplicateTableName + : global::SpacetimeDB.Internal.ITableView< + TestDuplicateTableName, + global::TestDuplicateTableName + > + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDuplicateTableName" + ); + + public static global::TestDuplicateTableName ReadGenFields( + System.IO.BinaryReader reader, + global::TestDuplicateTableName row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestDuplicateTableName), + ProductTypeRef: (uint) + new global::TestDuplicateTableName.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: [], + Constraints: [], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + TestDuplicateTableName, + global::TestDuplicateTableName + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + TestDuplicateTableName, + global::TestDuplicateTableName + >.DoIter(); + + public global::TestDuplicateTableName Insert(global::TestDuplicateTableName row) => + global::SpacetimeDB.Internal.ITableView< + TestDuplicateTableName, + global::TestDuplicateTableName + >.DoInsert(row); + + public bool Delete(global::TestDuplicateTableName row) => + global::SpacetimeDB.Internal.ITableView< + TestDuplicateTableName, + global::TestDuplicateTableName + >.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView< + TestDuplicateTableName, + global::TestDuplicateTableName + >.DoClear(); + } + + public readonly struct TestIndexIssues + : global::SpacetimeDB.Internal.ITableView + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues" + ); + + public static global::TestIndexIssues ReadGenFields( + System.IO.BinaryReader reader, + global::TestIndexIssues row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestIndexIssues), + ProductTypeRef: (uint) + new global::TestIndexIssues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: + [ + new( + SourceName: "TestIndexIssues__idx_btree", + AccessorName: "TestIndexWithoutColumns", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([]) + ), + new( + SourceName: "TestIndexIssues__idx_btree", + AccessorName: "TestIndexWithEmptyColumns", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([]) + ), + new( + SourceName: "TestIndexIssues__idx_btree", + AccessorName: "TestUnknownColumns", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([]) + ), + new( + SourceName: "TestIndexIssues_SelfIndexingColumn_idx_btree", + AccessorName: "SelfIndexingColumn", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + new( + SourceName: "TestIndexIssues_SecondaryIndexingColumn_idx_btree", + AccessorName: "SecondaryIndexingColumn", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) + ), + new( + SourceName: "TestIndexIssues_SelfIndexingColumn_idx_btree", + AccessorName: "TestUnexpectedColumns", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + ], + Constraints: [], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + TestIndexIssues, + global::TestIndexIssues + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + TestIndexIssues, + global::TestIndexIssues + >.DoIter(); + + public global::TestIndexIssues Insert(global::TestIndexIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestIndexIssues, + global::TestIndexIssues + >.DoInsert(row); + + public bool Delete(global::TestIndexIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestIndexIssues, + global::TestIndexIssues + >.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView< + TestIndexIssues, + global::TestIndexIssues + >.DoClear(); + + public sealed class TestIndexWithoutColumnsIndex() + : SpacetimeDB.Internal.IndexBase( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues__idx_btree" + ) + ) { } + + public TestIndexWithoutColumnsIndex TestIndexWithoutColumns => new(); + + public sealed class TestIndexWithEmptyColumnsIndex() + : SpacetimeDB.Internal.IndexBase( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues__idx_btree" + ) + ) { } + + public TestIndexWithEmptyColumnsIndex TestIndexWithEmptyColumns => new(); + + public sealed class TestUnknownColumnsIndex() + : SpacetimeDB.Internal.IndexBase( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues__idx_btree" + ) + ) { } + + public TestUnknownColumnsIndex TestUnknownColumns => new(); + + public sealed class SelfIndexingColumnIndex() + : SpacetimeDB.Internal.IndexBase( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues_SelfIndexingColumn_idx_btree" + ) + ) + { + public IEnumerable Filter(int SelfIndexingColumn) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); + + public ulong Delete(int SelfIndexingColumn) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); + + public IEnumerable Filter( + global::SpacetimeDB.Bound SelfIndexingColumn + ) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); + + public ulong Delete(global::SpacetimeDB.Bound SelfIndexingColumn) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); + } + + public SelfIndexingColumnIndex SelfIndexingColumn => new(); + + public sealed class SecondaryIndexingColumnIndex() + : SpacetimeDB.Internal.IndexBase( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues_SecondaryIndexingColumn_idx_btree" + ) + ) + { + public IEnumerable Filter(int SecondaryIndexingColumn) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + SecondaryIndexingColumn + ) + ); + + public ulong Delete(int SecondaryIndexingColumn) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + SecondaryIndexingColumn + ) + ); + + public IEnumerable Filter( + global::SpacetimeDB.Bound SecondaryIndexingColumn + ) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + SecondaryIndexingColumn + ) + ); + + public ulong Delete(global::SpacetimeDB.Bound SecondaryIndexingColumn) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + SecondaryIndexingColumn + ) + ); + } + + public SecondaryIndexingColumnIndex SecondaryIndexingColumn => new(); + + public sealed class TestUnexpectedColumnsIndex() + : SpacetimeDB.Internal.IndexBase( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues_SelfIndexingColumn_idx_btree" + ) + ) + { + public IEnumerable Filter(int SelfIndexingColumn) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); + + public ulong Delete(int SelfIndexingColumn) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); + + public IEnumerable Filter( + global::SpacetimeDB.Bound SelfIndexingColumn + ) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); + + public ulong Delete(global::SpacetimeDB.Bound SelfIndexingColumn) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); + } + + public TestUnexpectedColumnsIndex TestUnexpectedColumns => new(); + } + + public readonly struct TestScheduleWithMissingScheduleAtField + : global::SpacetimeDB.Internal.ITableView< + TestScheduleWithMissingScheduleAtField, + global::TestScheduleIssues + > + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithMissingScheduleAtField" + ); + + public static global::TestScheduleIssues ReadGenFields( + System.IO.BinaryReader reader, + global::TestScheduleIssues row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestScheduleWithMissingScheduleAtField), + ProductTypeRef: (uint) + new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: [], + Constraints: [], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithMissingScheduleAtField, + global::TestScheduleIssues + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithMissingScheduleAtField, + global::TestScheduleIssues + >.DoIter(); + + public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithMissingScheduleAtField, + global::TestScheduleIssues + >.DoInsert(row); + + public bool Delete(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithMissingScheduleAtField, + global::TestScheduleIssues + >.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithMissingScheduleAtField, + global::TestScheduleIssues + >.DoClear(); + } + + public readonly struct TestScheduleWithoutPrimaryKey + : global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutPrimaryKey, + global::TestScheduleIssues + > + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutPrimaryKey" + ); + + public static global::TestScheduleIssues ReadGenFields( + System.IO.BinaryReader reader, + global::TestScheduleIssues row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestScheduleWithoutPrimaryKey), + ProductTypeRef: (uint) + new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: [], + Constraints: [], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutPrimaryKey, + global::TestScheduleIssues + >.MakeSchedule("DummyScheduledReducer", 3); + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutPrimaryKey, + global::TestScheduleIssues + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutPrimaryKey, + global::TestScheduleIssues + >.DoIter(); + + public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutPrimaryKey, + global::TestScheduleIssues + >.DoInsert(row); + + public bool Delete(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutPrimaryKey, + global::TestScheduleIssues + >.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutPrimaryKey, + global::TestScheduleIssues + >.DoClear(); + } + + public readonly struct TestScheduleWithoutScheduleAt + : global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues + > + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutScheduleAt" + ); + + public static global::TestScheduleIssues ReadGenFields( + System.IO.BinaryReader reader, + global::TestScheduleIssues row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestScheduleWithoutScheduleAt), + ProductTypeRef: (uint) + new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [1], + Indexes: + [ + new( + SourceName: "TestScheduleWithoutScheduleAt_IdCorrectType_idx_btree", + AccessorName: "IdCorrectType", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues + >.MakeUniqueConstraint(1), + ], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues + >.DoIter(); + + public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues + >.DoInsert(row); + + public bool Delete(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues + >.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues + >.DoClear(); + + public sealed class IdCorrectTypeUniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues, + int, + SpacetimeDB.BSATN.I32 + > + { + internal IdCorrectTypeUniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutScheduleAt_IdCorrectType_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::TestScheduleIssues? Find(int key) => FindSingle(key); + + public global::TestScheduleIssues Update(global::TestScheduleIssues row) => + DoUpdate(row); + } + + public IdCorrectTypeUniqueIndex IdCorrectType => new(); + } + + public readonly struct TestScheduleWithWrongPrimaryKeyType + : global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + > + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongPrimaryKeyType" + ); + + public static global::TestScheduleIssues ReadGenFields( + System.IO.BinaryReader reader, + global::TestScheduleIssues row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestScheduleWithWrongPrimaryKeyType), + ProductTypeRef: (uint) + new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [0], + Indexes: + [ + new( + SourceName: "TestScheduleWithWrongPrimaryKeyType_IdWrongType_idx_btree", + AccessorName: "IdWrongType", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + >.MakeUniqueConstraint(0), + ], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + >.MakeSchedule("DummyScheduledReducer", 3); + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + >.DoIter(); + + public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + >.DoInsert(row); + + public bool Delete(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + >.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + >.DoClear(); + + public sealed class IdWrongTypeUniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues, + string, + SpacetimeDB.BSATN.String + > + { + internal IdWrongTypeUniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongPrimaryKeyType_IdWrongType_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::TestScheduleIssues? Find(string key) => FindSingle(key); + + public global::TestScheduleIssues Update(global::TestScheduleIssues row) => + DoUpdate(row); + } + + public IdWrongTypeUniqueIndex IdWrongType => new(); + } + + public readonly struct TestScheduleWithWrongScheduleAtType + : global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + > + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongScheduleAtType" + ); + + public static global::TestScheduleIssues ReadGenFields( + System.IO.BinaryReader reader, + global::TestScheduleIssues row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestScheduleWithWrongScheduleAtType), + ProductTypeRef: (uint) + new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [1], + Indexes: + [ + new( + SourceName: "TestScheduleWithWrongScheduleAtType_IdCorrectType_idx_btree", + AccessorName: "IdCorrectType", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + >.MakeUniqueConstraint(1), + ], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + >.MakeSchedule("DummyScheduledReducer", 2); + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + >.DoIter(); + + public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + >.DoInsert(row); + + public bool Delete(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + >.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + >.DoClear(); + + public sealed class IdCorrectTypeUniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues, + int, + SpacetimeDB.BSATN.I32 + > + { + internal IdCorrectTypeUniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongScheduleAtType_IdCorrectType_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::TestScheduleIssues? Find(int key) => FindSingle(key); + + public global::TestScheduleIssues Update(global::TestScheduleIssues row) => + DoUpdate(row); + } + + public IdCorrectTypeUniqueIndex IdCorrectType => new(); + } + + public readonly struct TestUniqueNotEquatable + : global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + > + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestUniqueNotEquatable" + ); + + public static global::TestUniqueNotEquatable ReadGenFields( + System.IO.BinaryReader reader, + global::TestUniqueNotEquatable row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestUniqueNotEquatable), + ProductTypeRef: (uint) + new global::TestUniqueNotEquatable.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [1], + Indexes: + [ + new( + SourceName: "TestUniqueNotEquatable_UniqueField_idx_btree", + AccessorName: "UniqueField", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + new( + SourceName: "TestUniqueNotEquatable_PrimaryKeyField_idx_btree", + AccessorName: "PrimaryKeyField", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + >.MakeUniqueConstraint(0), + global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + >.MakeUniqueConstraint(1), + ], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + >.DoIter(); + + public global::TestUniqueNotEquatable Insert(global::TestUniqueNotEquatable row) => + global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + >.DoInsert(row); + + public bool Delete(global::TestUniqueNotEquatable row) => + global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + >.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + >.DoClear(); + + public sealed class PrimaryKeyFieldUniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues, + SpacetimeDB.BSATN.Enum + > + { + internal PrimaryKeyFieldUniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestUniqueNotEquatable_PrimaryKeyField_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::TestUniqueNotEquatable? Find(TestEnumWithExplicitValues key) => + FindSingle(key); + + public global::TestUniqueNotEquatable Update(global::TestUniqueNotEquatable row) => + DoUpdate(row); + } + + public PrimaryKeyFieldUniqueIndex PrimaryKeyField => new(); + } +} + +sealed class view_def_ienumerable_return_from_filterViewDispatcher + : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_def_ienumerable_return_from_filter", + Index: 0, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.List< + TestScheduleIssues, + TestScheduleIssues.BSATN + >().GetAlgebraicType(registrar) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.ViewDefIEnumerableReturnFromFilter( + (SpacetimeDB.ViewContext)ctx + ); + var listSerializer = new SpacetimeDB.BSATN.List< + TestScheduleIssues, + TestScheduleIssues.BSATN + >(); + var listValue = global::System.Linq.Enumerable.ToList(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error( + "Error in view 'view_def_ienumerable_return_from_filter': " + e + ); + throw; + } + } +} + +sealed class view_def_ienumerable_return_from_iterViewDispatcher + : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_def_ienumerable_return_from_iter", + Index: 1, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.List().GetAlgebraicType( + registrar + ) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.ViewDefIEnumerableReturnFromIter((SpacetimeDB.ViewContext)ctx); + var listSerializer = new SpacetimeDB.BSATN.List(); + var listValue = global::System.Linq.Enumerable.ToList(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error( + "Error in view 'view_def_ienumerable_return_from_iter': " + e + ); + throw; + } + } +} + +sealed class view_def_no_contextViewDispatcher : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_def_no_context", + Index: 2, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.List().GetAlgebraicType( + registrar + ) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.ViewDefNoContext((SpacetimeDB.ViewContext)ctx); + var listSerializer = new SpacetimeDB.BSATN.List(); + var listValue = global::System.Linq.Enumerable.ToList(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'view_def_no_context': " + e); + throw; + } + } +} + +sealed class view_def_no_publicViewDispatcher : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_def_no_public", + Index: 3, + IsPublic: false, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.List().GetAlgebraicType( + registrar + ) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.ViewDefNoPublic((SpacetimeDB.ViewContext)ctx); + var listSerializer = new SpacetimeDB.BSATN.List(); + var listValue = global::System.Linq.Enumerable.ToList(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'view_def_no_public': " + e); + throw; + } + } +} + +sealed class view_def_wrong_contextViewDispatcher : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_def_wrong_context", + Index: 4, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.List().GetAlgebraicType( + registrar + ) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.ViewDefWrongContext((SpacetimeDB.ViewContext)ctx); + var listSerializer = new SpacetimeDB.BSATN.List(); + var listValue = global::System.Linq.Enumerable.ToList(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'view_def_wrong_context': " + e); + throw; + } + } +} + +sealed class view_def_wrong_returnViewDispatcher : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_def_wrong_return", + Index: 5, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new Player.BSATN().GetAlgebraicType(registrar) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.ViewDefWrongReturn((SpacetimeDB.ViewContext)ctx); + Player.BSATN returnRW = new(); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + returnRW.Write(writer, returnValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'view_def_wrong_return': " + e); + throw; + } + } +} + +sealed class view_no_deleteViewDispatcher : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_no_delete", + Index: 6, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.ValueOption().GetAlgebraicType( + registrar + ) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.ViewNoDelete((SpacetimeDB.ViewContext)ctx); + var listSerializer = SpacetimeDB.BSATN.ValueOption< + Player, + Player.BSATN + >.GetListSerializer(); + var listValue = ModuleRegistration.ToListOrEmpty(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'view_no_delete': " + e); + throw; + } + } +} + +sealed class view_no_insertViewDispatcher : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_no_insert", + Index: 7, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.ValueOption().GetAlgebraicType( + registrar + ) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.ViewNoInsert((SpacetimeDB.ViewContext)ctx); + var listSerializer = SpacetimeDB.BSATN.ValueOption< + Player, + Player.BSATN + >.GetListSerializer(); + var listValue = ModuleRegistration.ToListOrEmpty(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'view_no_insert': " + e); + throw; + } + } +} + +sealed class view_primary_key_missing_columnViewDispatcher : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_primary_key_missing_column", + Index: 8, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.List().GetAlgebraicType( + registrar + ) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.ViewPrimaryKeyMissingColumn((SpacetimeDB.ViewContext)ctx); + var listSerializer = new SpacetimeDB.BSATN.List(); + var listValue = global::System.Linq.Enumerable.ToList(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'view_primary_key_missing_column': " + e); + throw; + } + } +} + +sealed class view_primary_key_non_equatable_columnViewDispatcher + : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_primary_key_non_equatable_column", + Index: 9, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.List< + NonEquatableViewPrimaryKeyRow, + NonEquatableViewPrimaryKeyRow.BSATN + >().GetAlgebraicType(registrar) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.ViewPrimaryKeyNonEquatableColumn((SpacetimeDB.ViewContext)ctx); + var listSerializer = new SpacetimeDB.BSATN.List< + NonEquatableViewPrimaryKeyRow, + NonEquatableViewPrimaryKeyRow.BSATN + >(); + var listValue = global::System.Linq.Enumerable.ToList(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error( + "Error in view 'view_primary_key_non_equatable_column': " + e + ); + throw; + } + } +} + +sealed class view_primary_key_uses_non_bsatn_partial_fieldViewDispatcher + : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_primary_key_uses_non_bsatn_partial_field", + Index: 10, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.List< + ViewPrimaryKeyPartialRow, + ViewPrimaryKeyPartialRow.BSATN + >().GetAlgebraicType(registrar) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.ViewPrimaryKeyUsesNonBsatnPartialField( + (SpacetimeDB.ViewContext)ctx + ); + var listSerializer = new SpacetimeDB.BSATN.List< + ViewPrimaryKeyPartialRow, + ViewPrimaryKeyPartialRow.BSATN + >(); + var listValue = global::System.Linq.Enumerable.ToList(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error( + "Error in view 'view_primary_key_uses_non_bsatn_partial_field': " + e + ); + throw; + } + } +} + +sealed class view_primary_key_uses_wrong_source_nameViewDispatcher + : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_primary_key_uses_wrong_source_name", + Index: 11, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.List< + ViewPrimaryKeyRenamedRow, + ViewPrimaryKeyRenamedRow.BSATN + >().GetAlgebraicType(registrar) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.ViewPrimaryKeyUsesWrongSourceName( + (SpacetimeDB.ViewContext)ctx + ); + var listSerializer = new SpacetimeDB.BSATN.List< + ViewPrimaryKeyRenamedRow, + ViewPrimaryKeyRenamedRow.BSATN + >(); + var listValue = global::System.Linq.Enumerable.ToList(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error( + "Error in view 'view_primary_key_uses_wrong_source_name': " + e + ); + throw; + } + } +} + +sealed class view_def_index_no_mutationViewDispatcher : global::SpacetimeDB.Internal.IAnonymousView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeAnonymousViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_def_index_no_mutation", + Index: 0, + IsPublic: true, + IsAnonymous: true, + Params: [], + ReturnType: new SpacetimeDB.BSATN.ValueOption().GetAlgebraicType( + registrar + ) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IAnonymousViewContext ctx + ) + { + try + { + var returnValue = Module.ViewDefIndexNoMutation((SpacetimeDB.AnonymousViewContext)ctx); + var listSerializer = SpacetimeDB.BSATN.ValueOption< + Player, + Player.BSATN + >.GetListSerializer(); + var listValue = ModuleRegistration.ToListOrEmpty(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'view_def_index_no_mutation': " + e); + throw; + } + } +} + +sealed class view_def_no_anon_identityViewDispatcher : global::SpacetimeDB.Internal.IAnonymousView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeAnonymousViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_def_no_anon_identity", + Index: 1, + IsPublic: true, + IsAnonymous: true, + Params: [], + ReturnType: new SpacetimeDB.BSATN.ValueOption().GetAlgebraicType( + registrar + ) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IAnonymousViewContext ctx + ) + { + try + { + var returnValue = Module.ViewDefNoAnonIdentity((SpacetimeDB.AnonymousViewContext)ctx); + var listSerializer = SpacetimeDB.BSATN.ValueOption< + Player, + Player.BSATN + >.GetListSerializer(); + var listValue = ModuleRegistration.ToListOrEmpty(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'view_def_no_anon_identity': " + e); + throw; + } + } +} + +sealed class view_def_no_iterViewDispatcher : global::SpacetimeDB.Internal.IAnonymousView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeAnonymousViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_def_no_iter", + Index: 2, + IsPublic: true, + IsAnonymous: true, + Params: [], + ReturnType: new SpacetimeDB.BSATN.ValueOption().GetAlgebraicType( + registrar + ) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IAnonymousViewContext ctx + ) + { + try + { + var returnValue = Module.ViewDefNoIter((SpacetimeDB.AnonymousViewContext)ctx); + var listSerializer = SpacetimeDB.BSATN.ValueOption< + Player, + Player.BSATN + >.GetListSerializer(); + var listValue = ModuleRegistration.ToListOrEmpty(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'view_def_no_iter': " + e); + throw; + } + } +} + +sealed class view_def_returns_not_a_spacetime_typeViewDispatcher + : global::SpacetimeDB.Internal.IAnonymousView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeAnonymousViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "view_def_returns_not_a_spacetime_type", + Index: 3, + IsPublic: true, + IsAnonymous: true, + Params: [], + ReturnType: new SpacetimeDB.BSATN.ValueOption< + NotSpacetimeType, + NotSpacetimeType.BSATN + >().GetAlgebraicType(registrar) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IAnonymousViewContext ctx + ) + { + try + { + var returnValue = Module.ViewDefReturnsNotASpacetimeType( + (SpacetimeDB.AnonymousViewContext)ctx + ); + var listSerializer = SpacetimeDB.BSATN.ValueOption< + NotSpacetimeType, + NotSpacetimeType.BSATN + >.GetListSerializer(); + var listValue = ModuleRegistration.ToListOrEmpty(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error( + "Error in view 'view_def_returns_not_a_spacetime_type': " + e + ); + throw; + } + } +} + +namespace SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles +{ + public sealed class PlayerReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal PlayerReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "Player" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class IdentityIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PlayerReadOnly, + global::Player, + SpacetimeDB.Identity, + SpacetimeDB.Identity.BSATN + > + { + internal IdentityIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "Player_Identity_idx_btree" + ) + ) { } + + public global::Player? Find(SpacetimeDB.Identity key) => FindSingle(key); + } + + public IdentityIndex Identity => new(); + } + + public sealed class TestAutoIncNotIntegerReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal TestAutoIncNotIntegerReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestAutoIncNotInteger" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class IdentityFieldIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestAutoIncNotIntegerReadOnly, + global::TestAutoIncNotInteger, + string, + SpacetimeDB.BSATN.String + > + { + internal IdentityFieldIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestAutoIncNotInteger_IdentityField_idx_btree" + ) + ) { } + + public global::TestAutoIncNotInteger? Find(string key) => FindSingle(key); + } + + public IdentityFieldIndex IdentityField => new(); + } + + public sealed class TestDefaultFieldValuesReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal TestDefaultFieldValuesReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDefaultFieldValues" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + } + + public sealed class TestDuplicateTableNameReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal TestDuplicateTableNameReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDuplicateTableName" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + } + + public sealed class TestIndexIssuesReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal TestIndexIssuesReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class TestIndexWithoutColumnsIndex + : global::SpacetimeDB.Internal.ReadOnlyIndexBase + { + internal TestIndexWithoutColumnsIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues__idx_btree" + ) + ) { } + } + + public TestIndexWithoutColumnsIndex TestIndexWithoutColumns => new(); + + public sealed class TestIndexWithEmptyColumnsIndex + : global::SpacetimeDB.Internal.ReadOnlyIndexBase + { + internal TestIndexWithEmptyColumnsIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues__idx_btree" + ) + ) { } + } + + public TestIndexWithEmptyColumnsIndex TestIndexWithEmptyColumns => new(); + + public sealed class TestUnknownColumnsIndex + : global::SpacetimeDB.Internal.ReadOnlyIndexBase + { + internal TestUnknownColumnsIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues__idx_btree" + ) + ) { } + } + + public TestUnknownColumnsIndex TestUnknownColumns => new(); + + public sealed class SelfIndexingColumnIndex + : global::SpacetimeDB.Internal.ReadOnlyIndexBase + { + internal SelfIndexingColumnIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues_SelfIndexingColumn_idx_btree" + ) + ) { } + + public IEnumerable Filter(int SelfIndexingColumn) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); + + public IEnumerable Filter( + global::SpacetimeDB.Bound SelfIndexingColumn + ) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); + } + + public SelfIndexingColumnIndex SelfIndexingColumn => new(); + + public sealed class SecondaryIndexingColumnIndex + : global::SpacetimeDB.Internal.ReadOnlyIndexBase + { + internal SecondaryIndexingColumnIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues_SecondaryIndexingColumn_idx_btree" + ) + ) { } + + public IEnumerable Filter(int SecondaryIndexingColumn) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds( + SecondaryIndexingColumn + ) + ); + + public IEnumerable Filter( + global::SpacetimeDB.Bound SecondaryIndexingColumn + ) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds( + SecondaryIndexingColumn + ) + ); + } + + public SecondaryIndexingColumnIndex SecondaryIndexingColumn => new(); + + public sealed class TestUnexpectedColumnsIndex + : global::SpacetimeDB.Internal.ReadOnlyIndexBase + { + internal TestUnexpectedColumnsIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues_SelfIndexingColumn_idx_btree" + ) + ) { } + + public IEnumerable Filter(int SelfIndexingColumn) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); + + public IEnumerable Filter( + global::SpacetimeDB.Bound SelfIndexingColumn + ) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); + } + + public TestUnexpectedColumnsIndex TestUnexpectedColumns => new(); + } + + public sealed class TestScheduleWithMissingScheduleAtFieldReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal TestScheduleWithMissingScheduleAtFieldReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithMissingScheduleAtField" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + } + + public sealed class TestScheduleWithoutPrimaryKeyReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal TestScheduleWithoutPrimaryKeyReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutPrimaryKey" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + } + + public sealed class TestScheduleWithoutScheduleAtReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal TestScheduleWithoutScheduleAtReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutScheduleAt" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class IdCorrectTypeIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutScheduleAtReadOnly, + global::TestScheduleIssues, + int, + SpacetimeDB.BSATN.I32 + > + { + internal IdCorrectTypeIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutScheduleAt_IdCorrectType_idx_btree" + ) + ) { } + + public global::TestScheduleIssues? Find(int key) => FindSingle(key); + } + + public IdCorrectTypeIndex IdCorrectType => new(); + } + + public sealed class TestScheduleWithWrongPrimaryKeyTypeReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal TestScheduleWithWrongPrimaryKeyTypeReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongPrimaryKeyType" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class IdWrongTypeIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly, + global::TestScheduleIssues, + string, + SpacetimeDB.BSATN.String + > + { + internal IdWrongTypeIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongPrimaryKeyType_IdWrongType_idx_btree" + ) + ) { } + + public global::TestScheduleIssues? Find(string key) => FindSingle(key); + } + + public IdWrongTypeIndex IdWrongType => new(); + } + + public sealed class TestScheduleWithWrongScheduleAtTypeReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal TestScheduleWithWrongScheduleAtTypeReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongScheduleAtType" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class IdCorrectTypeIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly, + global::TestScheduleIssues, + int, + SpacetimeDB.BSATN.I32 + > + { + internal IdCorrectTypeIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongScheduleAtType_IdCorrectType_idx_btree" + ) + ) { } + + public global::TestScheduleIssues? Find(int key) => FindSingle(key); + } + + public IdCorrectTypeIndex IdCorrectType => new(); + } + + public sealed class TestUniqueNotEquatableReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal TestUniqueNotEquatableReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestUniqueNotEquatable" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class PrimaryKeyFieldIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestUniqueNotEquatableReadOnly, + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues, + SpacetimeDB.BSATN.Enum + > + { + internal PrimaryKeyFieldIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestUniqueNotEquatable_PrimaryKeyField_idx_btree" + ) + ) { } + + public global::TestUniqueNotEquatable? Find(TestEnumWithExplicitValues key) => + FindSingle(key); + } + + public PrimaryKeyFieldIndex PrimaryKeyField => new(); + } +} + +#if !NET10_0_OR_GREATER +namespace SpacetimeDB.Internal +{ + public sealed partial class LocalReadOnly + { + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PlayerReadOnly Player => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestAutoIncNotIntegerReadOnly TestAutoIncNotInteger => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestDefaultFieldValuesReadOnly TestDefaultFieldValues => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestDuplicateTableNameReadOnly TestDuplicateTableName => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestIndexIssuesReadOnly TestIndexIssues => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithMissingScheduleAtFieldReadOnly TestScheduleWithMissingScheduleAtField => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutPrimaryKeyReadOnly TestScheduleWithoutPrimaryKey => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutScheduleAtReadOnly TestScheduleWithoutScheduleAt => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly TestScheduleWithWrongPrimaryKeyType => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly TestScheduleWithWrongScheduleAtType => + new(); + public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestUniqueNotEquatableReadOnly TestUniqueNotEquatable => + new(); + } +} +#endif + +static class ModuleRegistration +{ + // Module host calls are single-threaded in Wasm today, so the generated + // entrypoints reuse buffers across calls to avoid per-invocation allocation. + private static byte[] reducerArgsBuffer = new byte[0x10_000]; + private static byte[] procedureArgsBuffer = new byte[0x10_000]; + private static byte[] httpRequestBuffer = new byte[0x10_000]; + private static byte[] httpRequestBodyBuffer = new byte[0x10_000]; + private static byte[] viewArgsBuffer = new byte[0x10_000]; + private static byte[] anonymousViewArgsBuffer = new byte[0x10_000]; + + sealed class __ReducerWithReservedPrefix : SpacetimeDB.Internal.IReducer + { + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(__ReducerWithReservedPrefix), + Params: [], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => null; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + Reducers.__ReducerWithReservedPrefix((SpacetimeDB.ReducerContext)ctx); + } + } + + sealed class DummyScheduledReducer : SpacetimeDB.Internal.IReducer + { + private static readonly TestScheduleIssues.BSATN tableRW = new(); + + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(DummyScheduledReducer), + Params: [new("table", tableRW.GetAlgebraicType(registrar))], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => null; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + TestScheduleIssues.DummyScheduledReducer( + (SpacetimeDB.ReducerContext)ctx, + tableRW.Read(reader) + ); + } + } + + sealed class OnReducerWithReservedPrefix : SpacetimeDB.Internal.IReducer + { + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(OnReducerWithReservedPrefix), + Params: [], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => null; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + Reducers.OnReducerWithReservedPrefix((SpacetimeDB.ReducerContext)ctx); + } + } + + sealed class TestDuplicateReducerKind1 : SpacetimeDB.Internal.IReducer + { + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestDuplicateReducerKind1), + Params: [], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => SpacetimeDB.Internal.Lifecycle.Init; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + Reducers.TestDuplicateReducerKind1((SpacetimeDB.ReducerContext)ctx); + } + } + + sealed class TestDuplicateReducerKind2 : SpacetimeDB.Internal.IReducer + { + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestDuplicateReducerKind2), + Params: [], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => SpacetimeDB.Internal.Lifecycle.Init; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + Reducers.TestDuplicateReducerKind2((SpacetimeDB.ReducerContext)ctx); + } + } + + sealed class TestDuplicateReducerName : SpacetimeDB.Internal.IReducer + { + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestDuplicateReducerName), + Params: [], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => null; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + Reducers.TestDuplicateReducerName((SpacetimeDB.ReducerContext)ctx); + } + } + + sealed class TestReducerReturnType : SpacetimeDB.Internal.IReducer + { + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestReducerReturnType), + Params: [], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => null; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + Reducers.TestReducerReturnType((SpacetimeDB.ReducerContext)ctx); + } + } + + sealed class TestReducerWithoutContext : SpacetimeDB.Internal.IReducer + { + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(TestReducerWithoutContext), + Params: [], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => null; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + throw new System.InvalidOperationException(); + } + } + + public static List ToListOrEmpty(T? value) + where T : struct => value is null ? new List() : new List { value.Value }; + + public static List ToListOrEmpty(T? value) + where T : class => value is null ? new List() : new List { value }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + // In AOT mode we're building a library. + // Main method won't be called automatically, so we need to export it as a preinit function. + [UnmanagedCallersOnly(EntryPoint = "__preinit__10_init_csharp")] +#else + // Prevent trimming of FFI exports that are invoked from C and not visible to C# trimmer. + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, typeof(ModuleRegistration))] +#endif + public static void Main() => Initialize(); + + internal static void Initialize() + { +#if !NET10_0_OR_GREATER + SpacetimeDB.Internal.Module.SetReducerContextConstructor( + (identity, connectionId, random, time) => + new SpacetimeDB.ReducerContext(identity, connectionId, random, time) + ); + SpacetimeDB.Internal.Module.SetViewContextConstructor( + identity => new SpacetimeDB.ViewContext( + identity, + new SpacetimeDB.Internal.LocalReadOnly() + ) + ); + SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor(() => + new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly()) + ); + SpacetimeDB.Internal.Module.SetProcedureContextConstructor( + (identity, connectionId, random, time) => + new SpacetimeDB.ProcedureContext(identity, connectionId, random, time) + ); + SpacetimeDB.Internal.Module.SetHandlerContextConstructor( + (random, time) => new SpacetimeDB.HandlerContext(random, time) + ); +#endif + +#if NET10_0_OR_GREATER + global::SpacetimeDB.Internal.Module.InstallNamespaces( + new global::SpacetimeDB.Internal.NamespaceRegistry( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + new global::System.Collections.Generic.KeyValuePair[] { } + ) + ); + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Register( + global::SpacetimeDB.Internal.Module.RootBuilder + ); +#else + Register(global::SpacetimeDB.Internal.Module.RootBuilder); +#endif + } + + internal static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null + ) + { + // HTTP routes retain the root routing API even for mounted modules. + httpBuilder ??= builder; + builder.SetCaseConversionPolicy(SpacetimeDB.CaseConversionPolicy.SnakeCase); + builder.RegisterExplicitIndexName( + "TestIndexIssues_SecondaryIndexingColumn_idx_btree", + "TestCanonicalNameWithoutAccessor" + ); + var __memoryStream = new MemoryStream(); + var __writer = new BinaryWriter(__memoryStream); + + builder.RegisterReducer<__ReducerWithReservedPrefix>(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + + // IMPORTANT: The order in which we register views matters. + // It must correspond to the order in which we call `GenerateDispatcherClass`. + // See the comment on `GenerateDispatcherClass` for more explanation. + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterAnonymousView(); + builder.RegisterAnonymousView(); + builder.RegisterAnonymousView(); + builder.RegisterAnonymousView(); + + builder.RegisterViewPrimaryKey("view_primary_key_missing_column", ["MissingIdentity"]); + builder.RegisterViewPrimaryKey("view_primary_key_non_equatable_column", ["Identity"]); + builder.RegisterViewPrimaryKey( + "view_primary_key_uses_non_bsatn_partial_field", + ["ExtraPartialIdentity"] + ); + builder.RegisterViewPrimaryKey( + "view_primary_key_uses_wrong_source_name", + ["renamed_identity"] + ); + + builder.RegisterTable< + global::Player, + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.Player + >(); + builder.RegisterTable< + global::TestAutoIncNotInteger, + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestAutoIncNotInteger + >(); + builder.RegisterTable< + global::TestDefaultFieldValues, + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDefaultFieldValues + >(); + builder.RegisterTable< + global::TestDuplicateTableName, + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDuplicateTableName + >(); + builder.RegisterTable< + global::TestIndexIssues, + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestIndexIssues + >(); + builder.RegisterTable< + global::TestScheduleIssues, + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithMissingScheduleAtField + >(); + builder.RegisterTable< + global::TestScheduleIssues, + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutPrimaryKey + >(); + builder.RegisterTable< + global::TestScheduleIssues, + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutScheduleAt + >(); + builder.RegisterTable< + global::TestScheduleIssues, + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongPrimaryKeyType + >(); + builder.RegisterTable< + global::TestScheduleIssues, + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongScheduleAtType + >(); + builder.RegisterTable< + global::TestUniqueNotEquatable, + global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestUniqueNotEquatable + >(); + + builder.RegisterClientVisibilityFilter(global::Module.MY_FILTER); + builder.RegisterClientVisibilityFilter(global::Module.MY_FOURTH_FILTER); + builder.RegisterClientVisibilityFilter(global::Module.MY_SECOND_FILTER); + builder.RegisterClientVisibilityFilter(global::Module.MY_THIRD_FILTER); + { + var value = new SpacetimeDB.BSATN.String(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, "A default string set by attribute"); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 1, array); + } + + { + var value = new SpacetimeDB.BSATN.U64(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, 2); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 10, array); + } + + { + var value = new SpacetimeDB.BSATN.I32(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, 2); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 11, array); + } + + { + var value = new SpacetimeDB.BSATN.I32(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, 2); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 12, array); + } + + { + var value = new SpacetimeDB.BSATN.F32(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, 2F); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 13, array); + } + + { + var value = new SpacetimeDB.BSATN.F64(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, 2); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 14, array); + } + + { + var value = new SpacetimeDB.BSATN.Enum(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, (MyEnum)2); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 15, array); + } + + { + var value = new SpacetimeDB.BSATN.ValueOption(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, null); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 16, array); + } + + { + var value = new SpacetimeDB.BSATN.Bool(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, true); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 2, array); + } + + { + var value = new SpacetimeDB.BSATN.I8(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, 2); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 3, array); + } + + { + var value = new SpacetimeDB.BSATN.U8(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, 2); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 4, array); + } + + { + var value = new SpacetimeDB.BSATN.I16(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, 2); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 5, array); + } + + { + var value = new SpacetimeDB.BSATN.U16(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, 2); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 6, array); + } + + { + var value = new SpacetimeDB.BSATN.I32(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, 2); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 7, array); + } + + { + var value = new SpacetimeDB.BSATN.U32(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, 2); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 8, array); + } + + { + var value = new SpacetimeDB.BSATN.I64(); + __memoryStream.Position = 0; + __memoryStream.SetLength(0); + value.Write(__writer, 2); + var array = __memoryStream.ToArray(); + builder.RegisterTableDefaultValue("TestDefaultFieldValues", 9, array); + } + } + + // Export entrypoints live in generated module code so all build modes can + // dispatch directly to concrete generated functions. +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__describe_module__")] +#endif + public static void __describe_module__(SpacetimeDB.Internal.BytesSink d) => + SpacetimeDB.Internal.Module.__describe_module__(d); + + private static SpacetimeDB.Internal.Errno __call_reducer_0( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + __ReducerWithReservedPrefix.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_reducer_1( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + DummyScheduledReducer.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_reducer_2( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + OnReducerWithReservedPrefix.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_reducer_3( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + TestDuplicateReducerKind1.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_reducer_4( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + TestDuplicateReducerKind2.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_reducer_5( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + TestDuplicateReducerName.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_reducer_6( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + TestReducerReturnType.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_reducer_7( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + TestReducerWithoutContext.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_view_0( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_def_ienumerable_return_from_filterViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_1( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_def_ienumerable_return_from_iterViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_2( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_def_no_contextViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_3( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_def_no_publicViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_4( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_def_wrong_contextViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_5( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_def_wrong_returnViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_6( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_no_deleteViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_7( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_no_insertViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_8( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_primary_key_missing_columnViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_9( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_primary_key_non_equatable_columnViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_10( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_primary_key_uses_non_bsatn_partial_fieldViewDispatcher.Invoke( + reader, + ctx + ); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_11( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_primary_key_uses_wrong_source_nameViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_anon_0( + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateAnonymousViewContext(); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref anonymousViewArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_def_index_no_mutationViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking anonymous view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_anon_1( + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateAnonymousViewContext(); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref anonymousViewArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_def_no_anon_identityViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking anonymous view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_anon_2( + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateAnonymousViewContext(); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref anonymousViewArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_def_no_iterViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking anonymous view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_anon_3( + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateAnonymousViewContext(); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref anonymousViewArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + var bytes = view_def_returns_not_a_spacetime_typeViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking anonymous view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_reducer__")] +#endif + public static SpacetimeDB.Internal.Errno __call_reducer__( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ReducerCount + ) + return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalReducer( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ReducerCount; + return SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ); +#else + return CallLocalReducer( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) => + id switch + { + 0 => __call_reducer_0( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 1 => __call_reducer_1( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 2 => __call_reducer_2( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 3 => __call_reducer_3( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 4 => __call_reducer_4( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 5 => __call_reducer_5( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 6 => __call_reducer_6( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 7 => __call_reducer_7( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + _ => SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ), + }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_procedure__")] +#endif + public static SpacetimeDB.Internal.Errno __call_procedure__( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink result_sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ProcedureCount + ) + return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalProcedure( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ProcedureCount; + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); +#else + return CallLocalProcedure( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink result_sink + ) => + id switch + { + _ => throw new System.ArgumentOutOfRangeException( + nameof(id), + id, + "Unknown procedure id" + ), + }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_http_handler__")] +#endif + public static SpacetimeDB.Internal.Errno __call_http_handler__( + int id, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource request, + SpacetimeDB.Internal.BytesSource request_body, + SpacetimeDB.Internal.BytesSink response_sink, + SpacetimeDB.Internal.BytesSink response_body_sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .HttpHandlerCount + ) + return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalHttpHandler( + localId, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .HttpHandlerCount; + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); +#else + return CallLocalHttpHandler( + id, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource request, + SpacetimeDB.Internal.BytesSource request_body, + SpacetimeDB.Internal.BytesSink response_sink, + SpacetimeDB.Internal.BytesSink response_body_sink + ) => + id switch + { + _ => throw new System.ArgumentOutOfRangeException( + nameof(id), + id, + "Unknown HTTP handler id" + ), + }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_view__")] +#endif + public static SpacetimeDB.Internal.Errno __call_view__( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return UnknownViewId(id); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ViewCount + ) + return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalView( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + args, + sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ViewCount; + return UnknownViewId(id); +#else + return CallLocalView(id, sender_0, sender_1, sender_2, sender_3, args, sink); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) => + id switch + { + 0 => __call_view_0(sender_0, sender_1, sender_2, sender_3, args, sink), + 1 => __call_view_1(sender_0, sender_1, sender_2, sender_3, args, sink), + 2 => __call_view_2(sender_0, sender_1, sender_2, sender_3, args, sink), + 3 => __call_view_3(sender_0, sender_1, sender_2, sender_3, args, sink), + 4 => __call_view_4(sender_0, sender_1, sender_2, sender_3, args, sink), + 5 => __call_view_5(sender_0, sender_1, sender_2, sender_3, args, sink), + 6 => __call_view_6(sender_0, sender_1, sender_2, sender_3, args, sink), + 7 => __call_view_7(sender_0, sender_1, sender_2, sender_3, args, sink), + 8 => __call_view_8(sender_0, sender_1, sender_2, sender_3, args, sink), + 9 => __call_view_9(sender_0, sender_1, sender_2, sender_3, args, sink), + 10 => __call_view_10(sender_0, sender_1, sender_2, sender_3, args, sink), + 11 => __call_view_11(sender_0, sender_1, sender_2, sender_3, args, sink), + _ => UnknownViewId(id), + }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_view_anon__")] +#endif + public static SpacetimeDB.Internal.Errno __call_view_anon__( + int id, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return UnknownAnonymousViewId(id); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .AnonymousViewCount + ) + return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalAnonymousView( + localId, + args, + sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .AnonymousViewCount; + return UnknownAnonymousViewId(id); +#else + return CallLocalAnonymousView(id, args, sink); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) => + id switch + { + 0 => __call_view_anon_0(args, sink), + 1 => __call_view_anon_1(args, sink), + 2 => __call_view_anon_2(args, sink), + 3 => __call_view_anon_3(args, sink), + _ => UnknownAnonymousViewId(id), + }; + + private static SpacetimeDB.Internal.Errno UnknownViewId(int id) + { + SpacetimeDB.Log.Error($"Unknown view id: {id}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + + private static SpacetimeDB.Internal.Errno UnknownAnonymousViewId(int id) + { + SpacetimeDB.Log.Error($"Unknown anonymous view id: {id}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } +} + +#pragma warning restore STDB_UNSTABLE +#pragma warning restore CS0436 diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#InAnotherNamespace.TestDuplicateTableName.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#InAnotherNamespace.TestDuplicateTableName.verified.cs new file mode 100644 index 00000000000..c48b0e9e277 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#InAnotherNamespace.TestDuplicateTableName.verified.cs @@ -0,0 +1,104 @@ +//HintName: InAnotherNamespace.TestDuplicateTableName.cs +// +#nullable enable + +partial class InAnotherNamespace +{ + partial struct TestDuplicateTableName + : System.IEquatable, + SpacetimeDB.BSATN.IStructuralReadWrite + { + public void ReadFields(System.IO.BinaryReader reader) { } + + public void WriteFields(System.IO.BinaryWriter writer) { } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => $"TestDuplicateTableName {{ }}"; + + public readonly partial struct BSATN + : SpacetimeDB.BSATN.IReadWrite + { + public InAnotherNamespace.TestDuplicateTableName Read(System.IO.BinaryReader reader) + { + var ___result = new InAnotherNamespace.TestDuplicateTableName(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write( + System.IO.BinaryWriter writer, + InAnotherNamespace.TestDuplicateTableName value + ) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType( + _ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] { } + ) + ); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + return 0; + } + +#nullable enable + public bool Equals(InAnotherNamespace.TestDuplicateTableName that) + { + return true; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as InAnotherNamespace.TestDuplicateTableName?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==( + InAnotherNamespace.TestDuplicateTableName this_, + InAnotherNamespace.TestDuplicateTableName that + ) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=( + InAnotherNamespace.TestDuplicateTableName this_, + InAnotherNamespace.TestDuplicateTableName that + ) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore + } // TestDuplicateTableName +} // InAnotherNamespace diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Player.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Player.verified.cs new file mode 100644 index 00000000000..afcd60afc5b --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Player.verified.cs @@ -0,0 +1,101 @@ +//HintName: Player.cs +// +#nullable enable + +partial struct Player : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) + { + Identity = BSATN.IdentityRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) + { + BSATN.IdentityRW.Write(writer, Identity); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => + $"Player {{ Identity = {SpacetimeDB.BSATN.StringUtil.GenericToString(Identity)} }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.Identity.BSATN IdentityRW = new(); + + public Player Read(System.IO.BinaryReader reader) + { + var ___result = new Player(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, Player value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("Identity", IdentityRW.GetAlgebraicType(registrar)), + } + )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashIdentity = Identity.GetHashCode(); + return ___hashIdentity; + } + +#nullable enable + public bool Equals(Player that) + { + var ___eqIdentity = this.Identity.Equals(that.Identity); + return ___eqIdentity; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as Player?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(Player this_, Player that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(Player this_, Player that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // Player diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.InAnotherNamespace.TestDuplicateReducerName.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.InAnotherNamespace.TestDuplicateReducerName.verified.cs new file mode 100644 index 00000000000..7614878cfbb --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.InAnotherNamespace.TestDuplicateReducerName.verified.cs @@ -0,0 +1,24 @@ +//HintName: Reducers.InAnotherNamespace.TestDuplicateReducerName.cs +// +#nullable enable + +partial class Reducers +{ + partial class InAnotherNamespace + { + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateTestDuplicateReducerName() + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestDuplicateReducerName) + ), + stream + ); + } + } // InAnotherNamespace +} // Reducers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.OnReducerWithReservedPrefix.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.OnReducerWithReservedPrefix.verified.cs new file mode 100644 index 00000000000..913aa1b37bc --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.OnReducerWithReservedPrefix.verified.cs @@ -0,0 +1,21 @@ +//HintName: Reducers.OnReducerWithReservedPrefix.cs +// +#nullable enable + +partial class Reducers +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateOnReducerWithReservedPrefix() + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(OnReducerWithReservedPrefix) + ), + stream + ); + } +} // Reducers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind1.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind1.verified.cs new file mode 100644 index 00000000000..4dc5091936a --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind1.verified.cs @@ -0,0 +1,21 @@ +//HintName: Reducers.TestDuplicateReducerKind1.cs +// +#nullable enable + +partial class Reducers +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateTestDuplicateReducerKind1() + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestDuplicateReducerKind1) + ), + stream + ); + } +} // Reducers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind2.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind2.verified.cs new file mode 100644 index 00000000000..d2fec96e7fc --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind2.verified.cs @@ -0,0 +1,21 @@ +//HintName: Reducers.TestDuplicateReducerKind2.cs +// +#nullable enable + +partial class Reducers +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateTestDuplicateReducerKind2() + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestDuplicateReducerKind2) + ), + stream + ); + } +} // Reducers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerName.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerName.verified.cs new file mode 100644 index 00000000000..cfa14ab306a --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerName.verified.cs @@ -0,0 +1,21 @@ +//HintName: Reducers.TestDuplicateReducerName.cs +// +#nullable enable + +partial class Reducers +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateTestDuplicateReducerName() + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestDuplicateReducerName) + ), + stream + ); + } +} // Reducers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerReturnType.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerReturnType.verified.cs new file mode 100644 index 00000000000..6b5a7281456 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerReturnType.verified.cs @@ -0,0 +1,21 @@ +//HintName: Reducers.TestReducerReturnType.cs +// +#nullable enable + +partial class Reducers +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateTestReducerReturnType() + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestReducerReturnType) + ), + stream + ); + } +} // Reducers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerWithoutContext.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerWithoutContext.verified.cs new file mode 100644 index 00000000000..d93e91533f0 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerWithoutContext.verified.cs @@ -0,0 +1,21 @@ +//HintName: Reducers.TestReducerWithoutContext.cs +// +#nullable enable + +partial class Reducers +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateTestReducerWithoutContext() + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestReducerWithoutContext) + ), + stream + ); + } +} // Reducers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.__ReducerWithReservedPrefix.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.__ReducerWithReservedPrefix.verified.cs new file mode 100644 index 00000000000..24c4515c3e1 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.__ReducerWithReservedPrefix.verified.cs @@ -0,0 +1,21 @@ +//HintName: Reducers.__ReducerWithReservedPrefix.cs +// +#nullable enable + +partial class Reducers +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediate__ReducerWithReservedPrefix() + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(__ReducerWithReservedPrefix) + ), + stream + ); + } +} // Reducers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestAutoIncNotInteger.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestAutoIncNotInteger.verified.cs new file mode 100644 index 00000000000..089c7521c72 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestAutoIncNotInteger.verified.cs @@ -0,0 +1,114 @@ +//HintName: TestAutoIncNotInteger.cs +// +#nullable enable + +partial struct TestAutoIncNotInteger + : System.IEquatable, + SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) + { + AutoIncField = BSATN.AutoIncFieldRW.Read(reader); + IdentityField = BSATN.IdentityFieldRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) + { + BSATN.AutoIncFieldRW.Write(writer, AutoIncField); + BSATN.IdentityFieldRW.Write(writer, IdentityField); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => + $"TestAutoIncNotInteger {{ AutoIncField = {SpacetimeDB.BSATN.StringUtil.GenericToString(AutoIncField)}, IdentityField = {SpacetimeDB.BSATN.StringUtil.GenericToString(IdentityField)} }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.F32 AutoIncFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.String IdentityFieldRW = new(); + + public TestAutoIncNotInteger Read(System.IO.BinaryReader reader) + { + var ___result = new TestAutoIncNotInteger(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, TestAutoIncNotInteger value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType( + _ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("AutoIncField", AutoIncFieldRW.GetAlgebraicType(registrar)), + new("IdentityField", IdentityFieldRW.GetAlgebraicType(registrar)), + } + ) + ); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashAutoIncField = AutoIncField.GetHashCode(); + var ___hashIdentityField = IdentityField == null ? 0 : IdentityField.GetHashCode(); + return ___hashAutoIncField ^ ___hashIdentityField; + } + +#nullable enable + public bool Equals(TestAutoIncNotInteger that) + { + var ___eqAutoIncField = this.AutoIncField.Equals(that.AutoIncField); + var ___eqIdentityField = + this.IdentityField == null + ? that.IdentityField == null + : this.IdentityField.Equals(that.IdentityField); + return ___eqAutoIncField && ___eqIdentityField; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as TestAutoIncNotInteger?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(TestAutoIncNotInteger this_, TestAutoIncNotInteger that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(TestAutoIncNotInteger this_, TestAutoIncNotInteger that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // TestAutoIncNotInteger diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestDefaultFieldValues.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestDefaultFieldValues.verified.cs new file mode 100644 index 00000000000..bf5c8f0b4fc --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestDefaultFieldValues.verified.cs @@ -0,0 +1,242 @@ +//HintName: TestDefaultFieldValues.cs +// +#nullable enable + +partial struct TestDefaultFieldValues + : System.IEquatable, + SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) + { + UniqueField = BSATN.UniqueFieldRW.Read(reader); + DefaultString = BSATN.DefaultStringRW.Read(reader); + DefaultBool = BSATN.DefaultBoolRW.Read(reader); + DefaultI8 = BSATN.DefaultI8RW.Read(reader); + DefaultU8 = BSATN.DefaultU8RW.Read(reader); + DefaultI16 = BSATN.DefaultI16RW.Read(reader); + DefaultU16 = BSATN.DefaultU16RW.Read(reader); + DefaultI32 = BSATN.DefaultI32RW.Read(reader); + DefaultU32 = BSATN.DefaultU32RW.Read(reader); + DefaultI64 = BSATN.DefaultI64RW.Read(reader); + DefaultU64 = BSATN.DefaultU64RW.Read(reader); + DefaultHex = BSATN.DefaultHexRW.Read(reader); + DefaultBin = BSATN.DefaultBinRW.Read(reader); + DefaultF32 = BSATN.DefaultF32RW.Read(reader); + DefaultF64 = BSATN.DefaultF64RW.Read(reader); + DefaultEnum = BSATN.DefaultEnumRW.Read(reader); + DefaultNull = BSATN.DefaultNullRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) + { + BSATN.UniqueFieldRW.Write(writer, UniqueField); + BSATN.DefaultStringRW.Write(writer, DefaultString); + BSATN.DefaultBoolRW.Write(writer, DefaultBool); + BSATN.DefaultI8RW.Write(writer, DefaultI8); + BSATN.DefaultU8RW.Write(writer, DefaultU8); + BSATN.DefaultI16RW.Write(writer, DefaultI16); + BSATN.DefaultU16RW.Write(writer, DefaultU16); + BSATN.DefaultI32RW.Write(writer, DefaultI32); + BSATN.DefaultU32RW.Write(writer, DefaultU32); + BSATN.DefaultI64RW.Write(writer, DefaultI64); + BSATN.DefaultU64RW.Write(writer, DefaultU64); + BSATN.DefaultHexRW.Write(writer, DefaultHex); + BSATN.DefaultBinRW.Write(writer, DefaultBin); + BSATN.DefaultF32RW.Write(writer, DefaultF32); + BSATN.DefaultF64RW.Write(writer, DefaultF64); + BSATN.DefaultEnumRW.Write(writer, DefaultEnum); + BSATN.DefaultNullRW.Write(writer, DefaultNull); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => + $"TestDefaultFieldValues {{ UniqueField = {SpacetimeDB.BSATN.StringUtil.GenericToString(UniqueField)}, DefaultString = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultString)}, DefaultBool = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultBool)}, DefaultI8 = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultI8)}, DefaultU8 = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultU8)}, DefaultI16 = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultI16)}, DefaultU16 = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultU16)}, DefaultI32 = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultI32)}, DefaultU32 = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultU32)}, DefaultI64 = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultI64)}, DefaultU64 = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultU64)}, DefaultHex = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultHex)}, DefaultBin = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultBin)}, DefaultF32 = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultF32)}, DefaultF64 = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultF64)}, DefaultEnum = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultEnum)}, DefaultNull = {SpacetimeDB.BSATN.StringUtil.GenericToString(DefaultNull)} }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.ValueOption< + int, + SpacetimeDB.BSATN.I32 + > UniqueFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.String DefaultStringRW = new(); + internal static readonly SpacetimeDB.BSATN.Bool DefaultBoolRW = new(); + internal static readonly SpacetimeDB.BSATN.I8 DefaultI8RW = new(); + internal static readonly SpacetimeDB.BSATN.U8 DefaultU8RW = new(); + internal static readonly SpacetimeDB.BSATN.I16 DefaultI16RW = new(); + internal static readonly SpacetimeDB.BSATN.U16 DefaultU16RW = new(); + internal static readonly SpacetimeDB.BSATN.I32 DefaultI32RW = new(); + internal static readonly SpacetimeDB.BSATN.U32 DefaultU32RW = new(); + internal static readonly SpacetimeDB.BSATN.I64 DefaultI64RW = new(); + internal static readonly SpacetimeDB.BSATN.U64 DefaultU64RW = new(); + internal static readonly SpacetimeDB.BSATN.I32 DefaultHexRW = new(); + internal static readonly SpacetimeDB.BSATN.I32 DefaultBinRW = new(); + internal static readonly SpacetimeDB.BSATN.F32 DefaultF32RW = new(); + internal static readonly SpacetimeDB.BSATN.F64 DefaultF64RW = new(); + internal static readonly SpacetimeDB.BSATN.Enum DefaultEnumRW = new(); + internal static readonly SpacetimeDB.BSATN.ValueOption< + MyStruct, + MyStruct.BSATN + > DefaultNullRW = new(); + + public TestDefaultFieldValues Read(System.IO.BinaryReader reader) + { + var ___result = new TestDefaultFieldValues(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, TestDefaultFieldValues value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType( + _ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("UniqueField", UniqueFieldRW.GetAlgebraicType(registrar)), + new("DefaultString", DefaultStringRW.GetAlgebraicType(registrar)), + new("DefaultBool", DefaultBoolRW.GetAlgebraicType(registrar)), + new("DefaultI8", DefaultI8RW.GetAlgebraicType(registrar)), + new("DefaultU8", DefaultU8RW.GetAlgebraicType(registrar)), + new("DefaultI16", DefaultI16RW.GetAlgebraicType(registrar)), + new("DefaultU16", DefaultU16RW.GetAlgebraicType(registrar)), + new("DefaultI32", DefaultI32RW.GetAlgebraicType(registrar)), + new("DefaultU32", DefaultU32RW.GetAlgebraicType(registrar)), + new("DefaultI64", DefaultI64RW.GetAlgebraicType(registrar)), + new("DefaultU64", DefaultU64RW.GetAlgebraicType(registrar)), + new("DefaultHex", DefaultHexRW.GetAlgebraicType(registrar)), + new("DefaultBin", DefaultBinRW.GetAlgebraicType(registrar)), + new("DefaultF32", DefaultF32RW.GetAlgebraicType(registrar)), + new("DefaultF64", DefaultF64RW.GetAlgebraicType(registrar)), + new("DefaultEnum", DefaultEnumRW.GetAlgebraicType(registrar)), + new("DefaultNull", DefaultNullRW.GetAlgebraicType(registrar)), + } + ) + ); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashUniqueField = UniqueField.GetHashCode(); + var ___hashDefaultString = DefaultString == null ? 0 : DefaultString.GetHashCode(); + var ___hashDefaultBool = DefaultBool.GetHashCode(); + var ___hashDefaultI8 = DefaultI8.GetHashCode(); + var ___hashDefaultU8 = DefaultU8.GetHashCode(); + var ___hashDefaultI16 = DefaultI16.GetHashCode(); + var ___hashDefaultU16 = DefaultU16.GetHashCode(); + var ___hashDefaultI32 = DefaultI32.GetHashCode(); + var ___hashDefaultU32 = DefaultU32.GetHashCode(); + var ___hashDefaultI64 = DefaultI64.GetHashCode(); + var ___hashDefaultU64 = DefaultU64.GetHashCode(); + var ___hashDefaultHex = DefaultHex.GetHashCode(); + var ___hashDefaultBin = DefaultBin.GetHashCode(); + var ___hashDefaultF32 = DefaultF32.GetHashCode(); + var ___hashDefaultF64 = DefaultF64.GetHashCode(); + var ___hashDefaultEnum = DefaultEnum.GetHashCode(); + var ___hashDefaultNull = DefaultNull.GetHashCode(); + return ___hashUniqueField + ^ ___hashDefaultString + ^ ___hashDefaultBool + ^ ___hashDefaultI8 + ^ ___hashDefaultU8 + ^ ___hashDefaultI16 + ^ ___hashDefaultU16 + ^ ___hashDefaultI32 + ^ ___hashDefaultU32 + ^ ___hashDefaultI64 + ^ ___hashDefaultU64 + ^ ___hashDefaultHex + ^ ___hashDefaultBin + ^ ___hashDefaultF32 + ^ ___hashDefaultF64 + ^ ___hashDefaultEnum + ^ ___hashDefaultNull; + } + +#nullable enable + public bool Equals(TestDefaultFieldValues that) + { + var ___eqUniqueField = System.Nullable.Equals(this.UniqueField, that.UniqueField); + var ___eqDefaultString = + this.DefaultString == null + ? that.DefaultString == null + : this.DefaultString.Equals(that.DefaultString); + var ___eqDefaultBool = this.DefaultBool.Equals(that.DefaultBool); + var ___eqDefaultI8 = this.DefaultI8.Equals(that.DefaultI8); + var ___eqDefaultU8 = this.DefaultU8.Equals(that.DefaultU8); + var ___eqDefaultI16 = this.DefaultI16.Equals(that.DefaultI16); + var ___eqDefaultU16 = this.DefaultU16.Equals(that.DefaultU16); + var ___eqDefaultI32 = this.DefaultI32.Equals(that.DefaultI32); + var ___eqDefaultU32 = this.DefaultU32.Equals(that.DefaultU32); + var ___eqDefaultI64 = this.DefaultI64.Equals(that.DefaultI64); + var ___eqDefaultU64 = this.DefaultU64.Equals(that.DefaultU64); + var ___eqDefaultHex = this.DefaultHex.Equals(that.DefaultHex); + var ___eqDefaultBin = this.DefaultBin.Equals(that.DefaultBin); + var ___eqDefaultF32 = this.DefaultF32.Equals(that.DefaultF32); + var ___eqDefaultF64 = this.DefaultF64.Equals(that.DefaultF64); + var ___eqDefaultEnum = this.DefaultEnum == that.DefaultEnum; + var ___eqDefaultNull = System.Nullable.Equals(this.DefaultNull, that.DefaultNull); + return ___eqUniqueField + && ___eqDefaultString + && ___eqDefaultBool + && ___eqDefaultI8 + && ___eqDefaultU8 + && ___eqDefaultI16 + && ___eqDefaultU16 + && ___eqDefaultI32 + && ___eqDefaultU32 + && ___eqDefaultI64 + && ___eqDefaultU64 + && ___eqDefaultHex + && ___eqDefaultBin + && ___eqDefaultF32 + && ___eqDefaultF64 + && ___eqDefaultEnum + && ___eqDefaultNull; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as TestDefaultFieldValues?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(TestDefaultFieldValues this_, TestDefaultFieldValues that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(TestDefaultFieldValues this_, TestDefaultFieldValues that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // TestDefaultFieldValues diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestDuplicateTableName.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestDuplicateTableName.verified.cs new file mode 100644 index 00000000000..f745f9847c0 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestDuplicateTableName.verified.cs @@ -0,0 +1,91 @@ +//HintName: TestDuplicateTableName.cs +// +#nullable enable + +partial struct TestDuplicateTableName + : System.IEquatable, + SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) { } + + public void WriteFields(System.IO.BinaryWriter writer) { } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => $"TestDuplicateTableName {{ }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + public TestDuplicateTableName Read(System.IO.BinaryReader reader) + { + var ___result = new TestDuplicateTableName(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, TestDuplicateTableName value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType( + _ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] { } + ) + ); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + return 0; + } + +#nullable enable + public bool Equals(TestDuplicateTableName that) + { + return true; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as TestDuplicateTableName?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(TestDuplicateTableName this_, TestDuplicateTableName that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(TestDuplicateTableName this_, TestDuplicateTableName that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // TestDuplicateTableName diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestIndexIssues.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestIndexIssues.verified.cs new file mode 100644 index 00000000000..3dd8a0a7425 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestIndexIssues.verified.cs @@ -0,0 +1,116 @@ +//HintName: TestIndexIssues.cs +// +#nullable enable + +partial struct TestIndexIssues + : System.IEquatable, + SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) + { + SelfIndexingColumn = BSATN.SelfIndexingColumnRW.Read(reader); + SecondaryIndexingColumn = BSATN.SecondaryIndexingColumnRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) + { + BSATN.SelfIndexingColumnRW.Write(writer, SelfIndexingColumn); + BSATN.SecondaryIndexingColumnRW.Write(writer, SecondaryIndexingColumn); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => + $"TestIndexIssues {{ SelfIndexingColumn = {SpacetimeDB.BSATN.StringUtil.GenericToString(SelfIndexingColumn)}, SecondaryIndexingColumn = {SpacetimeDB.BSATN.StringUtil.GenericToString(SecondaryIndexingColumn)} }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.I32 SelfIndexingColumnRW = new(); + internal static readonly SpacetimeDB.BSATN.I32 SecondaryIndexingColumnRW = new(); + + public TestIndexIssues Read(System.IO.BinaryReader reader) + { + var ___result = new TestIndexIssues(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, TestIndexIssues value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType( + _ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("SelfIndexingColumn", SelfIndexingColumnRW.GetAlgebraicType(registrar)), + new( + "SecondaryIndexingColumn", + SecondaryIndexingColumnRW.GetAlgebraicType(registrar) + ), + } + ) + ); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashSelfIndexingColumn = SelfIndexingColumn.GetHashCode(); + var ___hashSecondaryIndexingColumn = SecondaryIndexingColumn.GetHashCode(); + return ___hashSelfIndexingColumn ^ ___hashSecondaryIndexingColumn; + } + +#nullable enable + public bool Equals(TestIndexIssues that) + { + var ___eqSelfIndexingColumn = this.SelfIndexingColumn.Equals(that.SelfIndexingColumn); + var ___eqSecondaryIndexingColumn = this.SecondaryIndexingColumn.Equals( + that.SecondaryIndexingColumn + ); + return ___eqSelfIndexingColumn && ___eqSecondaryIndexingColumn; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as TestIndexIssues?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(TestIndexIssues this_, TestIndexIssues that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(TestIndexIssues this_, TestIndexIssues that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // TestIndexIssues diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.DummyScheduledReducer.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.DummyScheduledReducer.verified.cs new file mode 100644 index 00000000000..7bd10b3a732 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.DummyScheduledReducer.verified.cs @@ -0,0 +1,23 @@ +//HintName: TestScheduleIssues.DummyScheduledReducer.cs +// +#nullable enable + +partial struct TestScheduleIssues +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateDummyScheduledReducer( + TestScheduleIssues table + ) + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new TestScheduleIssues.BSATN().Write(writer, table); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(DummyScheduledReducer) + ), + stream + ); + } +} // TestScheduleIssues diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.verified.cs new file mode 100644 index 00000000000..cfbfc151870 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.verified.cs @@ -0,0 +1,142 @@ +//HintName: TestScheduleIssues.cs +// +#nullable enable + +partial struct TestScheduleIssues + : System.IEquatable, + SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) + { + IdWrongType = BSATN.IdWrongTypeRW.Read(reader); + IdCorrectType = BSATN.IdCorrectTypeRW.Read(reader); + ScheduleAtWrongType = BSATN.ScheduleAtWrongTypeRW.Read(reader); + ScheduleAtCorrectType = BSATN.ScheduleAtCorrectTypeRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) + { + BSATN.IdWrongTypeRW.Write(writer, IdWrongType); + BSATN.IdCorrectTypeRW.Write(writer, IdCorrectType); + BSATN.ScheduleAtWrongTypeRW.Write(writer, ScheduleAtWrongType); + BSATN.ScheduleAtCorrectTypeRW.Write(writer, ScheduleAtCorrectType); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => + $"TestScheduleIssues {{ IdWrongType = {SpacetimeDB.BSATN.StringUtil.GenericToString(IdWrongType)}, IdCorrectType = {SpacetimeDB.BSATN.StringUtil.GenericToString(IdCorrectType)}, ScheduleAtWrongType = {SpacetimeDB.BSATN.StringUtil.GenericToString(ScheduleAtWrongType)}, ScheduleAtCorrectType = {SpacetimeDB.BSATN.StringUtil.GenericToString(ScheduleAtCorrectType)} }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.String IdWrongTypeRW = new(); + internal static readonly SpacetimeDB.BSATN.I32 IdCorrectTypeRW = new(); + internal static readonly SpacetimeDB.BSATN.I32 ScheduleAtWrongTypeRW = new(); + internal static readonly SpacetimeDB.ScheduleAt.BSATN ScheduleAtCorrectTypeRW = new(); + + public TestScheduleIssues Read(System.IO.BinaryReader reader) + { + var ___result = new TestScheduleIssues(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, TestScheduleIssues value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType( + _ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("IdWrongType", IdWrongTypeRW.GetAlgebraicType(registrar)), + new("IdCorrectType", IdCorrectTypeRW.GetAlgebraicType(registrar)), + new( + "ScheduleAtWrongType", + ScheduleAtWrongTypeRW.GetAlgebraicType(registrar) + ), + new( + "ScheduleAtCorrectType", + ScheduleAtCorrectTypeRW.GetAlgebraicType(registrar) + ), + } + ) + ); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashIdWrongType = IdWrongType == null ? 0 : IdWrongType.GetHashCode(); + var ___hashIdCorrectType = IdCorrectType.GetHashCode(); + var ___hashScheduleAtWrongType = ScheduleAtWrongType.GetHashCode(); + var ___hashScheduleAtCorrectType = + ScheduleAtCorrectType == null ? 0 : ScheduleAtCorrectType.GetHashCode(); + return ___hashIdWrongType + ^ ___hashIdCorrectType + ^ ___hashScheduleAtWrongType + ^ ___hashScheduleAtCorrectType; + } + +#nullable enable + public bool Equals(TestScheduleIssues that) + { + var ___eqIdWrongType = + this.IdWrongType == null + ? that.IdWrongType == null + : this.IdWrongType.Equals(that.IdWrongType); + var ___eqIdCorrectType = this.IdCorrectType.Equals(that.IdCorrectType); + var ___eqScheduleAtWrongType = this.ScheduleAtWrongType.Equals(that.ScheduleAtWrongType); + var ___eqScheduleAtCorrectType = + this.ScheduleAtCorrectType == null + ? that.ScheduleAtCorrectType == null + : this.ScheduleAtCorrectType.Equals(that.ScheduleAtCorrectType); + return ___eqIdWrongType + && ___eqIdCorrectType + && ___eqScheduleAtWrongType + && ___eqScheduleAtCorrectType; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as TestScheduleIssues?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(TestScheduleIssues this_, TestScheduleIssues that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(TestScheduleIssues this_, TestScheduleIssues that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // TestScheduleIssues diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestTableTaggedEnum.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestTableTaggedEnum.verified.cs new file mode 100644 index 00000000000..38190b0b5f7 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestTableTaggedEnum.verified.cs @@ -0,0 +1,83 @@ +//HintName: TestTableTaggedEnum.cs +// +#nullable enable + +partial record TestTableTaggedEnum : System.IEquatable +{ + public sealed record X(int X_) : TestTableTaggedEnum + { + public override string ToString() => + $"X({SpacetimeDB.BSATN.StringUtil.GenericToString(X_)})"; + } + + public sealed record Y(int Y_) : TestTableTaggedEnum + { + public override string ToString() => + $"Y({SpacetimeDB.BSATN.StringUtil.GenericToString(Y_)})"; + } + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.I32 XRW = new(); + internal static readonly SpacetimeDB.BSATN.I32 YRW = new(); + + public TestTableTaggedEnum Read(System.IO.BinaryReader reader) + { + return reader.ReadByte() switch + { + 0 => new X(XRW.Read(reader)), + 1 => new Y(YRW.Read(reader)), + _ => throw new System.InvalidOperationException( + "Invalid tag value, this state should be unreachable." + ), + }; + } + + public void Write(System.IO.BinaryWriter writer, TestTableTaggedEnum value) + { + switch (value) + { + case X(var inner): + writer.Write((byte)0); + XRW.Write(writer, inner); + break; + case Y(var inner): + writer.Write((byte)1); + YRW.Write(writer, inner); + break; + } + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType( + _ => new SpacetimeDB.BSATN.AlgebraicType.Sum( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("X", XRW.GetAlgebraicType(registrar)), + new("Y", YRW.GetAlgebraicType(registrar)), + } + ) + ); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + switch (this) + { + case X(var inner): + var ___hashX = inner.GetHashCode(); + return ___hashX; + case Y(var inner): + var ___hashY = inner.GetHashCode(); + return ___hashY; + default: + return 0; + } + } +} // TestTableTaggedEnum diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestUniqueNotEquatable.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestUniqueNotEquatable.verified.cs new file mode 100644 index 00000000000..c635f1a06ee --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestUniqueNotEquatable.verified.cs @@ -0,0 +1,115 @@ +//HintName: TestUniqueNotEquatable.cs +// +#nullable enable + +partial struct TestUniqueNotEquatable + : System.IEquatable, + SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) + { + UniqueField = BSATN.UniqueFieldRW.Read(reader); + PrimaryKeyField = BSATN.PrimaryKeyFieldRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) + { + BSATN.UniqueFieldRW.Write(writer, UniqueField); + BSATN.PrimaryKeyFieldRW.Write(writer, PrimaryKeyField); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => + $"TestUniqueNotEquatable {{ UniqueField = {SpacetimeDB.BSATN.StringUtil.GenericToString(UniqueField)}, PrimaryKeyField = {SpacetimeDB.BSATN.StringUtil.GenericToString(PrimaryKeyField)} }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.ValueOption< + int, + SpacetimeDB.BSATN.I32 + > UniqueFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.Enum PrimaryKeyFieldRW = + new(); + + public TestUniqueNotEquatable Read(System.IO.BinaryReader reader) + { + var ___result = new TestUniqueNotEquatable(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, TestUniqueNotEquatable value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType( + _ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("UniqueField", UniqueFieldRW.GetAlgebraicType(registrar)), + new("PrimaryKeyField", PrimaryKeyFieldRW.GetAlgebraicType(registrar)), + } + ) + ); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashUniqueField = UniqueField.GetHashCode(); + var ___hashPrimaryKeyField = PrimaryKeyField.GetHashCode(); + return ___hashUniqueField ^ ___hashPrimaryKeyField; + } + +#nullable enable + public bool Equals(TestUniqueNotEquatable that) + { + var ___eqUniqueField = System.Nullable.Equals(this.UniqueField, that.UniqueField); + var ___eqPrimaryKeyField = this.PrimaryKeyField == that.PrimaryKeyField; + return ___eqUniqueField && ___eqPrimaryKeyField; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as TestUniqueNotEquatable?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(TestUniqueNotEquatable this_, TestUniqueNotEquatable that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(TestUniqueNotEquatable this_, TestUniqueNotEquatable that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // TestUniqueNotEquatable diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10.verified.txt b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10.verified.txt new file mode 100644 index 00000000000..3c87c799228 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10.verified.txt @@ -0,0 +1,629 @@ +{ + Diagnostics: [ + {/* + [AutoInc] + public float AutoIncField; + ^^^^^^^^^^^^ + +*/ + Message: Field AutoIncField is marked as AutoInc but it has a non-integer type float., + Severity: Error, + Descriptor: { + Id: STDB0002, + Title: AutoInc fields must be of integer type, + MessageFormat: Field {0} is marked as AutoInc but it has a non-integer type {1}., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + [AutoInc] + public string IdentityField; + ^^^^^^^^^^^^^ +} +*/ + Message: Field IdentityField is marked as AutoInc but it has a non-integer type string., + Severity: Error, + Descriptor: { + Id: STDB0002, + Title: AutoInc fields must be of integer type, + MessageFormat: Field {0} is marked as AutoInc but it has a non-integer type {1}., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + [Unique] + public int? UniqueField; + ^^^^^^^^^^^ + +*/ + Message: Field UniqueField is marked as Unique but it has a type int? which is not an equatable primitive., + Severity: Error, + Descriptor: { + Id: STDB0003, + Title: Unique fields must be equatable, + MessageFormat: Field {0} is marked as Unique but it has a type {1} which is not an equatable primitive., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* +[SpacetimeDB.Table] +public partial record TestTableTaggedEnum : SpacetimeDB.TaggedEnum<(int X, int Y)> { } + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*/ + Message: Table TestTableTaggedEnum is a tagged enum, which is not allowed., + Severity: Error, + Descriptor: { + Id: STDB0006, + Title: Tables cannot be tagged enums, + MessageFormat: Table {0} is a tagged enum, which is not allowed., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + [Unique] + public int? UniqueField; + ^^^^^^^^^^^ + +*/ + Message: Field UniqueField is marked as Unique but it has a type int? which is not an equatable primitive., + Severity: Error, + Descriptor: { + Id: STDB0003, + Title: Unique fields must be equatable, + MessageFormat: Field {0} is marked as Unique but it has a type {1} which is not an equatable primitive., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* +{ + [SpacetimeDB.Index.BTree(Accessor = "TestUnexpectedColumns", Columns = ["UnexpectedColumn"])] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + public int SelfIndexingColumn; +*/ + Message: Index attribute on a field applies directly to that field, so it doesn't accept the Columns parameter., + Severity: Error, + Descriptor: { + Id: STDB0015, + Title: Index attribute on a field must not specify Columns, + MessageFormat: Index attribute on a field applies directly to that field, so it doesn't accept the Columns parameter., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* +[SpacetimeDB.Table] +[SpacetimeDB.Index.BTree(Accessor = "TestIndexWithoutColumns")] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +[SpacetimeDB.Index.BTree(Accessor = "TestIndexWithEmptyColumns", Columns = [])] +*/ + Message: Index attribute doesn't specify columns., + Severity: Error, + Descriptor: { + Id: STDB0004, + Title: Index attribute must specify Columns, + MessageFormat: Index attribute doesn't specify columns., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* +[SpacetimeDB.Index.BTree(Accessor = "TestIndexWithoutColumns")] +[SpacetimeDB.Index.BTree(Accessor = "TestIndexWithEmptyColumns", Columns = [])] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +[SpacetimeDB.Index.BTree(Accessor = "TestUnknownColumns", Columns = ["UnknownColumn"])] +*/ + Message: Index attribute doesn't specify columns., + Severity: Error, + Descriptor: { + Id: STDB0004, + Title: Index attribute must specify Columns, + MessageFormat: Index attribute doesn't specify columns., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* +[SpacetimeDB.Index.BTree(Accessor = "TestIndexWithEmptyColumns", Columns = [])] +[SpacetimeDB.Index.BTree(Accessor = "TestUnknownColumns", Columns = ["UnknownColumn"])] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +[SpacetimeDB.Index.BTree(Columns = ["SelfIndexingColumn"])] +*/ + Message: Could not find the specified column UnknownColumn in TestIndexIssues., + Severity: Error, + Descriptor: { + Id: STDB0016, + Title: Unknown column, + MessageFormat: Could not find the specified column {0} in {1}., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* +[SpacetimeDB.Index.BTree(Accessor = "TestUnknownColumns", Columns = ["UnknownColumn"])] +[SpacetimeDB.Index.BTree(Columns = ["SelfIndexingColumn"])] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +[SpacetimeDB.Index.BTree( +*/ + Message: Index attribute on a table declaration must specify Accessor. Field-level index attributes may omit Accessor and default to the field name., + Severity: Error, + Descriptor: { + Id: STDB0029, + Title: Table-level index attributes must specify Accessor, + MessageFormat: Index attribute on a table declaration must specify Accessor. Field-level index attributes may omit Accessor and default to the field name., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* +[SpacetimeDB.Index.BTree(Columns = ["SelfIndexingColumn"])] +[SpacetimeDB.Index.BTree( + ^^^^^^^^^^^^^^^^^^^^^^^^ + Name = "TestCanonicalNameWithoutAccessor", +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Columns = ["SecondaryIndexingColumn"] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +)] +^ +public partial struct TestIndexIssues +*/ + Message: Index attribute on a table declaration must specify Accessor. Field-level index attributes may omit Accessor and default to the field name., + Severity: Error, + Descriptor: { + Id: STDB0029, + Title: Table-level index attributes must specify Accessor, + MessageFormat: Index attribute on a table declaration must specify Accessor. Field-level index attributes may omit Accessor and default to the field name., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + +[SpacetimeDB.Table( + ^^^^^^^^^^^^^^^^^^ + Accessor = "TestScheduleWithoutPrimaryKey", +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Scheduled = "DummyScheduledReducer", +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ScheduledAt = nameof(ScheduleAtCorrectType) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +)] +^ +[SpacetimeDB.Table( +*/ + Message: TestScheduleWithoutPrimaryKey is a scheduled table but doesn't have a primary key of type `ulong`., + Severity: Error, + Descriptor: { + Id: STDB0014, + Title: Invalid scheduled table declaration, + MessageFormat: {0}, + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* +)] +[SpacetimeDB.Table( + ^^^^^^^^^^^^^^^^^^ + Accessor = "TestScheduleWithWrongPrimaryKeyType", +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Scheduled = "DummyScheduledReducer", +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ScheduledAt = nameof(ScheduleAtCorrectType) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +)] +^ +[SpacetimeDB.Table(Accessor = "TestScheduleWithoutScheduleAt", Scheduled = "DummyScheduledReducer")] +*/ + Message: TestScheduleWithWrongPrimaryKeyType is a scheduled table but doesn't have a primary key of type `ulong`., + Severity: Error, + Descriptor: { + Id: STDB0014, + Title: Invalid scheduled table declaration, + MessageFormat: {0}, + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* +)] +[SpacetimeDB.Table(Accessor = "TestScheduleWithoutScheduleAt", Scheduled = "DummyScheduledReducer")] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +[SpacetimeDB.Table( +*/ + Message: Could not find the specified column ScheduledAt in TestScheduleIssues., + Severity: Error, + Descriptor: { + Id: STDB0016, + Title: Unknown column, + MessageFormat: Could not find the specified column {0} in {1}., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* +[SpacetimeDB.Table(Accessor = "TestScheduleWithoutScheduleAt", Scheduled = "DummyScheduledReducer")] +[SpacetimeDB.Table( + ^^^^^^^^^^^^^^^^^^ + Accessor = "TestScheduleWithWrongScheduleAtType", +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Scheduled = "DummyScheduledReducer", +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ScheduledAt = nameof(ScheduleAtWrongType) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +)] +^ +[SpacetimeDB.Table( +*/ + Message: TestScheduleWithWrongScheduleAtType is a scheduled table but doesn't have a primary key of type `ulong`., + Severity: Error, + Descriptor: { + Id: STDB0014, + Title: Invalid scheduled table declaration, + MessageFormat: {0}, + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* +)] +[SpacetimeDB.Table( + ^^^^^^^^^^^^^^^^^^ + Accessor = "TestScheduleWithMissingScheduleAtField", +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Scheduled = "DummyScheduledReducer", +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ScheduledAt = "MissingField" +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +)] +^ +public partial struct TestScheduleIssues +*/ + Message: Could not find the specified column MissingField in TestScheduleIssues., + Severity: Error, + Descriptor: { + Id: STDB0016, + Title: Unknown column, + MessageFormat: Could not find the specified column {0} in {1}., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + // Invalid: View definition missing Public=true + [SpacetimeDB.View(Accessor = "view_def_no_public")] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + public static List ViewDefNoPublic(ViewContext ctx) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + { +^^^^^ + return new List(); +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + } +^^^^^ + +*/ + Message: View 'ViewDefNoPublic' must have Public = true. Views are always public in SpacetimeDB., + Severity: Error, + Descriptor: { + Id: STDB0025, + Title: Views must be public, + MessageFormat: View '{0}' must have Public = true. Views are always public in SpacetimeDB., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + [SpacetimeDB.View(Accessor = "view_def_no_context", Public = true)] + public static List ViewDefNoContext() + ^^ + { +*/ + Message: View method ViewDefNoContext must have a first parameter of type ViewContext or AnonymousViewContext., + Severity: Error, + Descriptor: { + Id: STDB0022, + Title: Views must start with ViewContext or AnonymousViewContext, + MessageFormat: View method {0} must have a first parameter of type ViewContext or AnonymousViewContext., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + [SpacetimeDB.View(Accessor = "view_def_wrong_context", Public = true)] + public static List ViewDefWrongContext(ReducerContext ctx) + ^^^^^^^^^^^^^^^^^^^^ + { +*/ + Message: View method ViewDefWrongContext must have a first parameter of type ViewContext or AnonymousViewContext., + Severity: Error, + Descriptor: { + Id: STDB0022, + Title: Views must start with ViewContext or AnonymousViewContext, + MessageFormat: View method {0} must have a first parameter of type ViewContext or AnonymousViewContext., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + [SpacetimeDB.View(Accessor = "view_def_wrong_return", Public = true)] + public static Player ViewDefWrongReturn(ViewContext ctx) + ^^^^^^ + { +*/ + Message: View 'ViewDefWrongReturn' must return T?, List, IQuery, or IEnumerable., + Severity: Error, + Descriptor: { + Id: STDB0024, + Title: Views must return T?, List, IQuery, or IEnumerable, + MessageFormat: View '{0}' must return T?, List, IQuery, or IEnumerable., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + Public = true, + PrimaryKey = "MissingIdentity" + ^^^^^^^^^^^^^^^^^ + )] +*/ + Message: View 'ViewPrimaryKeyMissingColumn' declares primary key 'MissingIdentity', but row type 'Player' does not have a field with that source name., + Severity: Error, + Descriptor: { + Id: STDB0037, + Title: View primary key column not found, + MessageFormat: View '{0}' declares primary key '{1}', but row type '{2}' does not have a field with that source name., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + Public = true, + PrimaryKey = "renamed_identity" + ^^^^^^^^^^^^^^^^^^ + )] +*/ + Message: View 'ViewPrimaryKeyUsesWrongSourceName' declares primary key 'renamed_identity', but row type 'ViewPrimaryKeyRenamedRow' does not have a field with that source name., + Severity: Error, + Descriptor: { + Id: STDB0037, + Title: View primary key column not found, + MessageFormat: View '{0}' declares primary key '{1}', but row type '{2}' does not have a field with that source name., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + Public = true, + PrimaryKey = "ExtraPartialIdentity" + ^^^^^^^^^^^^^^^^^^^^^^ + )] +*/ + Message: View 'ViewPrimaryKeyUsesNonBsatnPartialField' declares primary key 'ExtraPartialIdentity', but row type 'ViewPrimaryKeyPartialRow' does not have a field with that source name., + Severity: Error, + Descriptor: { + Id: STDB0037, + Title: View primary key column not found, + MessageFormat: View '{0}' declares primary key '{1}', but row type '{2}' does not have a field with that source name., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + Public = true, + PrimaryKey = "Identity" + ^^^^^^^^^^ + )] +*/ + Message: View 'ViewPrimaryKeyNonEquatableColumn' declares primary key 'Identity', but its type 'NonEquatableViewPrimaryKey' is not supported for view primary keys., + Severity: Error, + Descriptor: { + Id: STDB0038, + Title: View primary key column type is not supported, + MessageFormat: View '{0}' declares primary key '{1}', but its type '{2}' is not supported for view primary keys., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + [SpacetimeDB.Reducer] + public static int TestReducerReturnType(ReducerContext ctx) => 0; + ^^^ + +*/ + Message: Reducer method TestReducerReturnType returns int instead of void., + Severity: Error, + Descriptor: { + Id: STDB0001, + Title: [SpacetimeDB.Reducer] methods must return void, + MessageFormat: Reducer method {0} returns {1} instead of void., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + [SpacetimeDB.Reducer] + public static void TestReducerWithoutContext() { } + ^^ + +*/ + Message: Reducer method TestReducerWithoutContext does not have a ReducerContext parameter., + Severity: Error, + Descriptor: { + Id: STDB0008, + Title: Reducers must have a first argument of type ReducerContext, + MessageFormat: Reducer method {0} does not have a ReducerContext parameter., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + [SpacetimeDB.Reducer] + public static void OnReducerWithReservedPrefix(ReducerContext ctx) { } + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*/ + Message: Reducer method OnReducerWithReservedPrefix starts with 'On', which is a reserved prefix., + Severity: Error, + Descriptor: { + Id: STDB0010, + Title: Reducer method has a reserved name prefix, + MessageFormat: Reducer method {0} starts with '{1}', which is a reserved prefix., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + [SpacetimeDB.Reducer] + public static void __ReducerWithReservedPrefix(ReducerContext ctx) { } + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} +*/ + Message: Reducer method __ReducerWithReservedPrefix starts with '__', which is a reserved prefix., + Severity: Error, + Descriptor: { + Id: STDB0010, + Title: Reducer method has a reserved name prefix, + MessageFormat: Reducer method {0} starts with '{1}', which is a reserved prefix., + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + { + Location: , + Message: Several reducers are assigned to the same lifecycle kind Init: Reducers.TestDuplicateReducerKind1, Reducers.TestDuplicateReducerKind2, + Severity: Error, + Descriptor: { + Id: STDB0013, + Title: Multiple reducers of the same kind, + MessageFormat: Several reducers are assigned to the same lifecycle kind {0}: {1}, + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + { + Location: , + Message: Reducer with the same export name TestDuplicateReducerName is registered in multiple places: Reducers.TestDuplicateReducerName, Reducers.InAnotherNamespace.TestDuplicateReducerName, + Severity: Error, + Descriptor: { + Id: STDB0007, + Title: Duplicate exports, + MessageFormat: {0} with the same export name {1} is registered in multiple places: {2}, + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + { + Location: , + Message: Table with the same export name TestDuplicateTableName is registered in multiple places: global::TestDuplicateTableName, global::InAnotherNamespace.TestDuplicateTableName, + Severity: Error, + Descriptor: { + Id: STDB0007, + Title: Duplicate exports, + MessageFormat: {0} with the same export name {1} is registered in multiple places: {2}, + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + { + Location: , + Message: TableReadOnly with the same export name TestDuplicateTableNameReadOnly is registered in multiple places: global::TestDuplicateTableName, global::InAnotherNamespace.TestDuplicateTableName, + Severity: Error, + Descriptor: { + Id: STDB0007, + Title: Duplicate exports, + MessageFormat: {0} with the same export name {1} is registered in multiple places: {2}, + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + [SpacetimeDB.ClientVisibilityFilter] + private Filter MY_FILTER = new Filter.Sql("SELECT * FROM TestAutoIncNotInteger"); + ^^^^^^^^^ + +*/ + Message: Field MY_FILTER is marked as [ClientVisibilityFilter] but it is not public static readonly, + Severity: Error, + Descriptor: { + Id: STDB0018, + Title: ClientVisibilityFilters must be public static readonly, + MessageFormat: Field {0} is marked as [ClientVisibilityFilter] but it is not public static readonly, + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + [SpacetimeDB.ClientVisibilityFilter] + public static Filter MY_SECOND_FILTER = new Filter.Sql("SELECT * FROM TestAutoIncNotInteger"); + ^^^^^^^^^^^^^^^^ + +*/ + Message: Field MY_SECOND_FILTER is marked as [ClientVisibilityFilter] but it is not public static readonly, + Severity: Error, + Descriptor: { + Id: STDB0018, + Title: ClientVisibilityFilters must be public static readonly, + MessageFormat: Field {0} is marked as [ClientVisibilityFilter] but it is not public static readonly, + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + }, + {/* + [SpacetimeDB.ClientVisibilityFilter] + public static readonly string MY_THIRD_FILTER = "SELECT * FROM TestAutoIncNotInteger"; + ^^^^^^^^^^^^^^^ + +*/ + Message: Field MY_THIRD_FILTER is marked as ClientVisibilityFilter but it has type string which is not SpacetimeDB.Filter, + Severity: Error, + Descriptor: { + Id: STDB0017, + Title: ClientVisibilityFilters must be Filters, + MessageFormat: Field {0} is marked as ClientVisibilityFilter but it has type {1} which is not SpacetimeDB.Filter, + Category: SpacetimeDB, + DefaultSeverity: Error, + IsEnabledByDefault: true + } + } + ] +} \ No newline at end of file diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#MyStruct.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#MyStruct.verified.cs index ab145aab509..41cd8c2b038 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#MyStruct.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#MyStruct.verified.cs @@ -44,7 +44,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( new SpacetimeDB.BSATN.AggregateElement[] { - new("x", xRW.GetAlgebraicType(registrar)) + new("x", xRW.GetAlgebraicType(registrar)), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#NonEquatableViewPrimaryKey.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#NonEquatableViewPrimaryKey.verified.cs index b4d6dd416f9..9bbc641a529 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#NonEquatableViewPrimaryKey.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#NonEquatableViewPrimaryKey.verified.cs @@ -47,7 +47,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar _ => new SpacetimeDB.BSATN.AlgebraicType.Product( new SpacetimeDB.BSATN.AggregateElement[] { - new("Value", ValueRW.GetAlgebraicType(registrar)) + new("Value", ValueRW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#NonEquatableViewPrimaryKeyRow.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#NonEquatableViewPrimaryKeyRow.verified.cs index fad8680539f..b9c056ee796 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#NonEquatableViewPrimaryKeyRow.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#NonEquatableViewPrimaryKeyRow.verified.cs @@ -48,7 +48,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar _ => new SpacetimeDB.BSATN.AlgebraicType.Product( new SpacetimeDB.BSATN.AggregateElement[] { - new("Identity", IdentityRW.GetAlgebraicType(registrar)) + new("Identity", IdentityRW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestTaggedEnumField.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestTaggedEnumField.verified.cs index 9f0584e348e..780ddd42135 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestTaggedEnumField.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestTaggedEnumField.verified.cs @@ -27,10 +27,9 @@ public TestTaggedEnumField Read(System.IO.BinaryReader reader) { 0 => new X(XRW.Read(reader)), 1 => new Y(YRW.Read(reader)), - _ - => throw new System.InvalidOperationException( - "Invalid tag value, this state should be unreachable." - ) + _ => throw new System.InvalidOperationException( + "Invalid tag value, this state should be unreachable." + ), }; } @@ -57,7 +56,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new SpacetimeDB.BSATN.AggregateElement[] { new("X", XRW.GetAlgebraicType(registrar)), - new("Y", YRW.GetAlgebraicType(registrar)) + new("Y", YRW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestTaggedEnumInlineTuple.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestTaggedEnumInlineTuple.verified.cs index 761bdacb92e..4a7c01f40f2 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestTaggedEnumInlineTuple.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestTaggedEnumInlineTuple.verified.cs @@ -19,10 +19,9 @@ public TestTaggedEnumInlineTuple Read(System.IO.BinaryReader reader) return reader.ReadByte() switch { 0 => new Item1(Item1RW.Read(reader)), - _ - => throw new System.InvalidOperationException( - "Invalid tag value, this state should be unreachable." - ) + _ => throw new System.InvalidOperationException( + "Invalid tag value, this state should be unreachable." + ), }; } @@ -44,7 +43,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar _ => new SpacetimeDB.BSATN.AlgebraicType.Sum( new SpacetimeDB.BSATN.AggregateElement[] { - new("Item1", Item1RW.GetAlgebraicType(registrar)) + new("Item1", Item1RW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestTypeParams_T_.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestTypeParams_T_.verified.cs index 8558fa804b3..abbf7b396af 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestTypeParams_T_.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestTypeParams_T_.verified.cs @@ -47,7 +47,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar _ => new SpacetimeDB.BSATN.AlgebraicType.Product( new SpacetimeDB.BSATN.AggregateElement[] { - new("Field", FieldRW.GetAlgebraicType(registrar)) + new("Field", FieldRW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestUnsupportedType.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestUnsupportedType.verified.cs index 83e1269067f..afa81298881 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestUnsupportedType.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#TestUnsupportedType.verified.cs @@ -67,7 +67,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar UnsupportedSystemTypeRW.GetAlgebraicType(registrar) ), new("UnresolvedType", UnresolvedTypeRW.GetAlgebraicType(registrar)), - new("UnsupportedEnum", UnsupportedEnumRW.GetAlgebraicType(registrar)) + new("UnsupportedEnum", UnsupportedEnumRW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#ViewPrimaryKeyPartialRow.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#ViewPrimaryKeyPartialRow.verified.cs index 4ce530acedf..657b472a823 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#ViewPrimaryKeyPartialRow.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#ViewPrimaryKeyPartialRow.verified.cs @@ -47,7 +47,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar _ => new SpacetimeDB.BSATN.AlgebraicType.Product( new SpacetimeDB.BSATN.AggregateElement[] { - new("DeclaredIdentity", DeclaredIdentityRW.GetAlgebraicType(registrar)) + new("DeclaredIdentity", DeclaredIdentityRW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#ViewPrimaryKeyRenamedRow.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#ViewPrimaryKeyRenamedRow.verified.cs index bc6c6faed44..7478b6d8c3f 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#ViewPrimaryKeyRenamedRow.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Type#ViewPrimaryKeyRenamedRow.verified.cs @@ -47,7 +47,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar _ => new SpacetimeDB.BSATN.AlgebraicType.Product( new SpacetimeDB.BSATN.AggregateElement[] { - new("RenamedIdentity", RenamedIdentityRW.GetAlgebraicType(registrar)) + new("RenamedIdentity", RenamedIdentityRW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#DemoTable.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#DemoTable.verified.cs index c43a88b3f68..07460ecb9af 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#DemoTable.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#DemoTable.verified.cs @@ -48,7 +48,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new SpacetimeDB.BSATN.AggregateElement[] { new("Id", IdRW.GetAlgebraicType(registrar)), - new("Value", ValueRW.GetAlgebraicType(registrar)) + new("Value", ValueRW.GetAlgebraicType(registrar)), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs index ad729dadac1..fcaf4a85b89 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs @@ -1,20 +1,28 @@ //HintName: FFI.cs // #nullable enable -// The runtime already defines SpacetimeDB.Internal.LocalReadOnly in Runtime\Internal\Module.cs as an empty partial type. -// This is needed so every module build doesn't generate a full LocalReadOnly type, but just adds on to the existing. -// We extend it here with generated table accessors, and just need to suppress the duplicate-type warning. +// .NET 8 generates a module-local LocalReadOnly which shadows the runtime shell. #pragma warning disable CS0436 #pragma warning disable STDB_UNSTABLE +#if NET10_0_OR_GREATER +global using SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C; +#endif using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Internal = SpacetimeDB.Internal; using TxContext = SpacetimeDB.Internal.TxContext; +#if NET10_0_OR_GREATER +[assembly: global::SpacetimeDB.ModuleDescriptorAttribute( + typeof(global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor) +)] + +#endif namespace SpacetimeDB { +#if !NET10_0_OR_GREATER public readonly struct DemoTableCols { public readonly global::SpacetimeDB.Col Id; @@ -46,9 +54,11 @@ public readonly partial struct QueryBuilder > DemoTable() => new("DemoTable", new DemoTableCols("DemoTable"), new DemoTableIxCols("DemoTable")); } +#endif public static class Handlers { } +#if !NET10_0_OR_GREATER public sealed record ReducerContext : DbContext, Internal.IReducerContext { public global::SpacetimeDB.ModuleEnvironment Env => default; @@ -302,7 +312,206 @@ public sealed record AnonymousViewContext internal AnonymousViewContext(Internal.LocalReadOnly db) : base(db) { } } +#endif +} + +#if NET10_0_OR_GREATER +namespace SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +{ + public static partial class AssemblyDescriptor + { + public const string LifecycleReducers = ""; + public const int ReducerCount = 1; + public const int ProcedureCount = 1; + public const int HttpHandlerCount = 0; + public const int ViewCount = 1; + public const int AnonymousViewCount = 0; + + public static global::SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink error + ) => + global::ModuleRegistration.CallLocalReducer( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink result_sink + ) => + global::ModuleRegistration.CallLocalProcedure( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource request, + global::SpacetimeDB.Internal.BytesSource request_body, + global::SpacetimeDB.Internal.BytesSink response_sink, + global::SpacetimeDB.Internal.BytesSink response_body_sink + ) => + global::ModuleRegistration.CallLocalHttpHandler( + id, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => + global::ModuleRegistration.CallLocalView( + id, + sender_0, + sender_1, + sender_2, + sender_3, + args, + sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => global::ModuleRegistration.CallLocalAnonymousView(id, args, sink); + + public static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null + ) => global::ModuleRegistration.Register(builder, httpBuilder); + + public readonly struct Tables + { + public global::SpacetimeDB.Internal.TableHandles.DemoTable DemoTable => new(); + } + + public readonly struct ReadOnlyTables + { + public global::SpacetimeDB.Internal.ViewHandles.DemoTableReadOnly DemoTable => new(); + } + + public readonly partial struct Queries { } + } + + public static class LocalTableExtensions + { + extension(global::SpacetimeDB.Local db) + { + public global::SpacetimeDB.Internal.TableHandles.DemoTable DemoTable => new(); + } + } + + public static class ReadOnlyTableExtensions + { + extension(global::SpacetimeDB.Internal.LocalReadOnly db) + { + public global::SpacetimeDB.Internal.ViewHandles.DemoTableReadOnly DemoTable => new(); + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) { } + } + + public readonly struct DemoTableCols + { + public readonly global::SpacetimeDB.Col Id; + public readonly global::SpacetimeDB.Col Value; + + internal DemoTableCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "Id"); + Value = new global::SpacetimeDB.Col(tableName, "Value"); + } + } + + public readonly struct DemoTableIxCols + { + public readonly global::SpacetimeDB.IxCol Id; + + internal DemoTableIxCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "Id"); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::DemoTable, + DemoTableCols, + DemoTableIxCols + > DemoTable() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable" + ); + return new(tableName, new DemoTableCols(tableName), new DemoTableIxCols(tableName)); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::DemoTable, + DemoTableCols, + DemoTableIxCols + > DemoTable() => new AssemblyDescriptor.Queries().DemoTable(); + } + } } +#endif namespace SpacetimeDB.Internal.TableHandles { @@ -336,14 +545,14 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "DemoTable_Id_idx_btree", AccessorName: "ById", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) + ), ], Constraints: [ global::SpacetimeDB.Internal.ITableView< DemoTable, global::DemoTable - >.MakeUniqueConstraint(0) + >.MakeUniqueConstraint(0), ], Sequences: [], TableType: SpacetimeDB.Internal.TableType.User, @@ -376,7 +585,12 @@ public ulong Clear() => global::SpacetimeDB.Internal.ITableView.DoClear(); public sealed class IdUniqueIndex - : UniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + DemoTable, + global::DemoTable, + int, + SpacetimeDB.BSATN.I32 + > { internal IdUniqueIndex() : base("DemoTable_Id_idx_btree") { } @@ -510,6 +724,7 @@ internal ByIdIndex() } } +#if !NET10_0_OR_GREATER namespace SpacetimeDB.Internal { public sealed partial class LocalReadOnly @@ -517,6 +732,7 @@ public sealed partial class LocalReadOnly public global::SpacetimeDB.Internal.ViewHandles.DemoTableReadOnly DemoTable => new(); } } +#endif static class ModuleRegistration { @@ -585,8 +801,11 @@ public static List ToListOrEmpty(T? value) // Prevent trimming of FFI exports that are invoked from C and not visible to C# trimmer. [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, typeof(ModuleRegistration))] #endif - public static void Main() + public static void Main() => Initialize(); + + internal static void Initialize() { +#if !NET10_0_OR_GREATER SpacetimeDB.Internal.Module.SetReducerContextConstructor( (identity, connectionId, random, time) => new SpacetimeDB.ReducerContext(identity, connectionId, random, time) @@ -597,48 +816,60 @@ public static void Main() new SpacetimeDB.Internal.LocalReadOnly() ) ); - SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor( - () => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly()) + SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor(() => + new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly()) ); SpacetimeDB.Internal.Module.SetProcedureContextConstructor( (identity, connectionId, random, time) => new SpacetimeDB.ProcedureContext(identity, connectionId, random, time) ); - SpacetimeDB.Internal.Module.SetCaseConversionPolicy( - SpacetimeDB.CaseConversionPolicy.SnakeCase - ); - SpacetimeDB.Internal.Module.RegisterExplicitTableName("DemoTable", "canonical_table"); - SpacetimeDB.Internal.Module.RegisterExplicitFunctionName( - "DemoReducer", - "canonical_reducer" + SpacetimeDB.Internal.Module.SetHandlerContextConstructor( + (random, time) => new SpacetimeDB.HandlerContext(random, time) ); - SpacetimeDB.Internal.Module.RegisterExplicitFunctionName( - "DemoProcedure", - "canonical_procedure" +#endif + +#if NET10_0_OR_GREATER + global::SpacetimeDB.Internal.Module.InstallNamespaces( + new global::SpacetimeDB.Internal.NamespaceRegistry( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + new global::System.Collections.Generic.KeyValuePair[] { } + ) ); - SpacetimeDB.Internal.Module.RegisterExplicitFunctionName("demo_view", "canonical_view"); - SpacetimeDB.Internal.Module.RegisterExplicitIndexName( - "DemoTable_Id_idx_btree", - "canonical_index" + global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Register( + global::SpacetimeDB.Internal.Module.RootBuilder ); +#else + Register(global::SpacetimeDB.Internal.Module.RootBuilder); +#endif + } - SpacetimeDB.Internal.Module.SetHandlerContextConstructor( - (random, time) => new SpacetimeDB.HandlerContext(random, time) - ); + internal static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null + ) + { + // HTTP routes retain the root routing API even for mounted modules. + httpBuilder ??= builder; + builder.SetCaseConversionPolicy(SpacetimeDB.CaseConversionPolicy.SnakeCase); + builder.RegisterExplicitTableName("DemoTable", "canonical_table"); + builder.RegisterExplicitFunctionName("DemoReducer", "canonical_reducer"); + builder.RegisterExplicitFunctionName("DemoProcedure", "canonical_procedure"); + builder.RegisterExplicitFunctionName("demo_view", "canonical_view"); + builder.RegisterExplicitIndexName("DemoTable_Id_idx_btree", "canonical_index"); var __memoryStream = new MemoryStream(); var __writer = new BinaryWriter(__memoryStream); - SpacetimeDB.Internal.Module.RegisterReducer(); - SpacetimeDB.Internal.Module.RegisterProcedure(); + builder.RegisterReducer(); + builder.RegisterProcedure(); // IMPORTANT: The order in which we register views matters. // It must correspond to the order in which we call `GenerateDispatcherClass`. // See the comment on `GenerateDispatcherClass` for more explanation. - SpacetimeDB.Internal.Module.RegisterView(); + builder.RegisterView(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::DemoTable, - SpacetimeDB.Internal.TableHandles.DemoTable + global::SpacetimeDB.Internal.TableHandles.DemoTable >(); } @@ -772,26 +1003,92 @@ public static SpacetimeDB.Internal.Errno __call_reducer__( SpacetimeDB.Timestamp timestamp, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink error + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ReducerCount + ) + return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalReducer( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ReducerCount; + return SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ); +#else + return CallLocalReducer( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error ) => id switch { - 0 - => __call_reducer_0( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - _ - => SpacetimeDB.Internal.Module.WriteReducerError( - error, - new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") - ) + 0 => __call_reducer_0( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + _ => SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ), }; #if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER @@ -808,27 +1105,87 @@ public static SpacetimeDB.Internal.Errno __call_procedure__( SpacetimeDB.Timestamp timestamp, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink result_sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ProcedureCount + ) + return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalProcedure( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ProcedureCount; + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); +#else + return CallLocalProcedure( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink result_sink ) => id switch { - 0 - => __call_procedure_0( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - result_sink - ), - _ - => throw new System.ArgumentOutOfRangeException( - nameof(id), - id, - "Unknown procedure id" - ) + 0 => __call_procedure_0( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ), + _ => throw new System.ArgumentOutOfRangeException( + nameof(id), + id, + "Unknown procedure id" + ), }; #if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER @@ -841,15 +1198,64 @@ public static SpacetimeDB.Internal.Errno __call_http_handler__( SpacetimeDB.Internal.BytesSource request_body, SpacetimeDB.Internal.BytesSink response_sink, SpacetimeDB.Internal.BytesSink response_body_sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .HttpHandlerCount + ) + return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalHttpHandler( + localId, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .HttpHandlerCount; + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); +#else + return CallLocalHttpHandler( + id, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource request, + SpacetimeDB.Internal.BytesSource request_body, + SpacetimeDB.Internal.BytesSink response_sink, + SpacetimeDB.Internal.BytesSink response_body_sink ) => id switch { - _ - => throw new System.ArgumentOutOfRangeException( - nameof(id), - id, - "Unknown HTTP handler id" - ) + _ => throw new System.ArgumentOutOfRangeException( + nameof(id), + id, + "Unknown HTTP handler id" + ), }; #if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER @@ -863,11 +1269,56 @@ public static SpacetimeDB.Internal.Errno __call_view__( ulong sender_3, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return UnknownViewId(id); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ViewCount + ) + return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalView( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + args, + sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ViewCount; + return UnknownViewId(id); +#else + return CallLocalView(id, sender_0, sender_1, sender_2, sender_3, args, sink); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink ) => id switch { 0 => __call_view_0(sender_0, sender_1, sender_2, sender_3, args, sink), - _ => UnknownViewId(id) + _ => UnknownViewId(id), }; #if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER @@ -877,10 +1328,47 @@ public static SpacetimeDB.Internal.Errno __call_view_anon__( int id, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return UnknownAnonymousViewId(id); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .AnonymousViewCount + ) + return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalAnonymousView( + localId, + args, + sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .AnonymousViewCount; + return UnknownAnonymousViewId(id); +#else + return CallLocalAnonymousView(id, args, sink); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink ) => id switch { - _ => UnknownAnonymousViewId(id) + _ => UnknownAnonymousViewId(id), }; private static SpacetimeDB.Internal.Errno UnknownViewId(int id) diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#DemoTable.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#DemoTable.verified.cs new file mode 100644 index 00000000000..07460ecb9af --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#DemoTable.verified.cs @@ -0,0 +1,107 @@ +//HintName: DemoTable.cs +// +#nullable enable + +partial struct DemoTable : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) + { + Id = BSATN.IdRW.Read(reader); + Value = BSATN.ValueRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) + { + BSATN.IdRW.Write(writer, Id); + BSATN.ValueRW.Write(writer, Value); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => + $"DemoTable {{ Id = {SpacetimeDB.BSATN.StringUtil.GenericToString(Id)}, Value = {SpacetimeDB.BSATN.StringUtil.GenericToString(Value)} }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.I32 IdRW = new(); + internal static readonly SpacetimeDB.BSATN.I32 ValueRW = new(); + + public DemoTable Read(System.IO.BinaryReader reader) + { + var ___result = new DemoTable(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, DemoTable value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("Id", IdRW.GetAlgebraicType(registrar)), + new("Value", ValueRW.GetAlgebraicType(registrar)), + } + )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashId = Id.GetHashCode(); + var ___hashValue = Value.GetHashCode(); + return ___hashId ^ ___hashValue; + } + +#nullable enable + public bool Equals(DemoTable that) + { + var ___eqId = this.Id.Equals(that.Id); + var ___eqValue = this.Value.Equals(that.Value); + return ___eqId && ___eqValue; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as DemoTable?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(DemoTable this_, DemoTable that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(DemoTable this_, DemoTable that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // DemoTable diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs new file mode 100644 index 00000000000..771d8daf951 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs @@ -0,0 +1,1416 @@ +//HintName: FFI.cs +// +#nullable enable +// .NET 8 generates a module-local LocalReadOnly which shadows the runtime shell. +#pragma warning disable CS0436 +#pragma warning disable STDB_UNSTABLE + +#if NET10_0_OR_GREATER +global using SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C; +#endif +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Internal = SpacetimeDB.Internal; +using TxContext = SpacetimeDB.Internal.TxContext; +#if NET10_0_OR_GREATER +[assembly: global::SpacetimeDB.ModuleDescriptorAttribute( + typeof(global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor) +)] + +#endif + +namespace SpacetimeDB +{ +#if !NET10_0_OR_GREATER + public readonly struct DemoTableCols + { + public readonly global::SpacetimeDB.Col Id; + public readonly global::SpacetimeDB.Col Value; + + internal DemoTableCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "Id"); + Value = new global::SpacetimeDB.Col(tableName, "Value"); + } + } + + public readonly struct DemoTableIxCols + { + public readonly global::SpacetimeDB.IxCol Id; + + internal DemoTableIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "Id"); + } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::DemoTable, + DemoTableCols, + DemoTableIxCols + > DemoTable() => + new("DemoTable", new DemoTableCols("DemoTable"), new DemoTableIxCols("DemoTable")); + } +#endif + + public static class Handlers { } + +#if !NET10_0_OR_GREATER + public sealed record ReducerContext : DbContext, Internal.IReducerContext + { + public readonly Identity Sender; + public readonly ConnectionId? ConnectionId; + public readonly Random Rng; + public readonly Timestamp Timestamp; + public readonly AuthCtx SenderAuth; + + // **Note:** must be 0..=u32::MAX + internal int CounterUuid; + public Identity DatabaseIdentity => Internal.IReducerContext.GetDatabaseIdentity(); + + // We keep this property for compatibility with existing module code. + [global::System.Obsolete( + "ReducerContext.Identity is deprecated. Use DatabaseIdentity instead." + )] + public Identity Identity => DatabaseIdentity; + + internal ReducerContext( + Identity identity, + ConnectionId? connectionId, + Random random, + Timestamp time, + AuthCtx? senderAuth = null + ) + { + Sender = identity; + ConnectionId = connectionId; + Rng = random; + Timestamp = time; + SenderAuth = senderAuth ?? AuthCtx.BuildFromSystemTables(connectionId, identity); + CounterUuid = 0; + } + + /// + /// Create a new random `v4` using the built-in RNG. + /// + /// + /// This method fills the random bytes using the context RNG. + /// + /// + /// + /// var uuid = ctx.NewUuidV4(); + /// Log.Info(uuid); + /// + /// + public Uuid NewUuidV4() + { + var bytes = new byte[16]; + Rng.NextBytes(bytes); + return Uuid.FromRandomBytesV4(bytes); + } + + /// + /// Create a new sortable `v7` using the built-in RNG, monotonic counter, + /// and timestamp. + /// + /// + /// A newly generated `v7` that is monotonically ordered + /// and suitable for use as a primary key or for ordered storage. + /// + /// + /// Thrown if generation fails. + /// + /// + /// + /// [SpacetimeDB.Reducer] + /// public static Guid GenerateUuidV7(ReducerContext ctx) + /// { + /// Guid uuid = ctx.NewUuidV7(); + /// Log.Info(uuid); + /// } + /// + /// + public Uuid NewUuidV7() + { + var bytes = new byte[4]; + Rng.NextBytes(bytes); + return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); + } + } + + public sealed partial class ProcedureContext : global::SpacetimeDB.ProcedureContextBase + { + private readonly Local _db = new(); + + internal ProcedureContext( + Identity identity, + ConnectionId? connectionId, + Random random, + Timestamp time + ) + : base(identity, connectionId, random, time) { } + + protected override global::SpacetimeDB.LocalBase CreateLocal() => _db; + + protected override global::SpacetimeDB.ProcedureTxContextBase CreateTxContext( + Internal.TxContext inner + ) => _cached ??= new ProcedureTxContext(inner); + + private ProcedureTxContext? _cached; + + public Local Db => _db; + + public TResult WithTx(Func body) => + base.WithTx(tx => body((ProcedureTxContext)tx)); + + public TxOutcome TryWithTx( + Func> body + ) + where TError : Exception => base.TryWithTx(tx => body((ProcedureTxContext)tx)); + + /// + /// Create a new random `v4` using the built-in RNG. + /// + /// + /// This method fills the random bytes using the context RNG. + /// + /// + /// + /// var uuid = ctx.NewUuidV4(); + /// Log.Info(uuid); + /// + /// + public Uuid NewUuidV4() + { + var bytes = new byte[16]; + Rng.NextBytes(bytes); + return Uuid.FromRandomBytesV4(bytes); + } + + /// + /// Create a new sortable `v7` using the built-in RNG, monotonic counter, + /// and timestamp. + /// + /// + /// A newly generated `v7` that is monotonically ordered + /// and suitable for use as a primary key or for ordered storage. + /// + /// + /// Thrown if UUID generation fails. + /// + /// + /// + /// [SpacetimeDB.Procedure] + /// public static Guid GenerateUuidV7(ReducerContext ctx) + /// { + /// Guid uuid = ctx.NewUuidV7(); + /// Log.Info(uuid); + /// } + /// + /// + public Uuid NewUuidV7() + { + var bytes = new byte[4]; + Rng.NextBytes(bytes); + return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); + } + } + + public sealed partial class HandlerContext : global::SpacetimeDB.HandlerContextBase + { + private readonly Local _db = new(); + + internal HandlerContext(Random random, Timestamp time) + : base(random, time) { } + + protected override global::SpacetimeDB.LocalBase CreateLocal() => _db; + + protected override global::SpacetimeDB.HandlerTxContextBase CreateTxContext( + Internal.TxContext inner + ) => _cached ??= new HandlerTxContext(inner); + + private HandlerTxContext? _cached; + + [Experimental("STDB_UNSTABLE")] + public TResult WithTx(Func body) => + base.WithTx(tx => body((HandlerTxContext)tx)); + + [Experimental("STDB_UNSTABLE")] + public TxOutcome TryWithTx( + Func> body + ) + where TError : Exception => base.TryWithTx(tx => body((HandlerTxContext)tx)); + + public Uuid NewUuidV4() + { + var bytes = new byte[16]; + Rng.NextBytes(bytes); + return Uuid.FromRandomBytesV4(bytes); + } + + public Uuid NewUuidV7() + { + var bytes = new byte[4]; + Rng.NextBytes(bytes); + return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); + } + } + + public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase + { + internal ProcedureTxContext(Internal.TxContext inner) + : base(inner) { } + + public new Local Db => (Local)base.Db; + } + + [Experimental("STDB_UNSTABLE")] + public sealed class HandlerTxContext : global::SpacetimeDB.HandlerTxContextBase + { + internal HandlerTxContext(Internal.TxContext inner) + : base(inner) { } + + public new Local Db => (Local)base.Db; + } + + public sealed class Local : global::SpacetimeDB.LocalBase + { + public global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.DemoTable DemoTable => + new(); + } + + public sealed record ViewContext : DbContext, Internal.IViewContext + { + public Identity Sender { get; } + + public QueryBuilder From => default; + + internal ViewContext(Identity sender, Internal.LocalReadOnly db) + : base(db) + { + Sender = sender; + } + } + + public sealed record AnonymousViewContext + : DbContext, + Internal.IAnonymousViewContext + { + public QueryBuilder From => default; + + internal AnonymousViewContext(Internal.LocalReadOnly db) + : base(db) { } + } +#endif +} + +#if NET10_0_OR_GREATER +namespace SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +{ + public static partial class AssemblyDescriptor + { + public const string LifecycleReducers = ""; + public const int ReducerCount = 1; + public const int ProcedureCount = 1; + public const int HttpHandlerCount = 0; + public const int ViewCount = 1; + public const int AnonymousViewCount = 0; + + public static global::SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink error + ) => + global::ModuleRegistration.CallLocalReducer( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink result_sink + ) => + global::ModuleRegistration.CallLocalProcedure( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource request, + global::SpacetimeDB.Internal.BytesSource request_body, + global::SpacetimeDB.Internal.BytesSink response_sink, + global::SpacetimeDB.Internal.BytesSink response_body_sink + ) => + global::ModuleRegistration.CallLocalHttpHandler( + id, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => + global::ModuleRegistration.CallLocalView( + id, + sender_0, + sender_1, + sender_2, + sender_3, + args, + sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => global::ModuleRegistration.CallLocalAnonymousView(id, args, sink); + + public static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null + ) => global::ModuleRegistration.Register(builder, httpBuilder); + + public readonly struct Tables + { + public global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.DemoTable DemoTable => + new(); + } + + public readonly struct ReadOnlyTables + { + public global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.DemoTableReadOnly DemoTable => + new(); + } + + public readonly partial struct Queries { } + } + + public static class LocalTableExtensions + { + extension(global::SpacetimeDB.Local db) + { + public global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.DemoTable DemoTable => + new(); + } + } + + public static class ReadOnlyTableExtensions + { + extension(global::SpacetimeDB.Internal.LocalReadOnly db) + { + public global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.DemoTableReadOnly DemoTable => + new(); + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) { } + } + + public readonly struct DemoTableCols + { + public readonly global::SpacetimeDB.Col Id; + public readonly global::SpacetimeDB.Col Value; + + internal DemoTableCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "Id"); + Value = new global::SpacetimeDB.Col(tableName, "Value"); + } + } + + public readonly struct DemoTableIxCols + { + public readonly global::SpacetimeDB.IxCol Id; + + internal DemoTableIxCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "Id"); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::DemoTable, + DemoTableCols, + DemoTableIxCols + > DemoTable() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable" + ); + return new(tableName, new DemoTableCols(tableName), new DemoTableIxCols(tableName)); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::DemoTable, + DemoTableCols, + DemoTableIxCols + > DemoTable() => new AssemblyDescriptor.Queries().DemoTable(); + } + } +} +#endif + +namespace SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles +{ + public readonly struct DemoTable + : global::SpacetimeDB.Internal.ITableView + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable" + ); + + public static global::DemoTable ReadGenFields( + System.IO.BinaryReader reader, + global::DemoTable row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(DemoTable), + ProductTypeRef: (uint) + new global::DemoTable.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [0], + Indexes: + [ + new( + SourceName: "DemoTable_Id_idx_btree", + AccessorName: "Id", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + new( + SourceName: "DemoTable_Id_idx_btree", + AccessorName: "ById", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + DemoTable, + global::DemoTable + >.MakeUniqueConstraint(0), + ], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Public, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView.DoIter(); + + public global::DemoTable Insert(global::DemoTable row) => + global::SpacetimeDB.Internal.ITableView.DoInsert(row); + + public bool Delete(global::DemoTable row) => + global::SpacetimeDB.Internal.ITableView.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView.DoClear(); + + public sealed class IdUniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + DemoTable, + global::DemoTable, + int, + SpacetimeDB.BSATN.I32 + > + { + internal IdUniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable_Id_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::DemoTable? Find(int key) => FindSingle(key); + + public global::DemoTable Update(global::DemoTable row) => DoUpdate(row); + } + + public IdUniqueIndex Id => new(); + + public sealed class ByIdIndex() + : SpacetimeDB.Internal.IndexBase( + global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable_Id_idx_btree" + ) + ) + { + public IEnumerable Filter(int Id) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(Id)); + + public ulong Delete(int Id) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(Id)); + + public IEnumerable Filter(global::SpacetimeDB.Bound Id) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(Id)); + + public ulong Delete(global::SpacetimeDB.Bound Id) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(Id)); + } + + public ByIdIndex ById => new(); + } +} + +sealed class demo_viewViewDispatcher : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "demo_view", + Index: 0, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.List().GetAlgebraicType( + registrar + ) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Reducers.DemoView((SpacetimeDB.ViewContext)ctx); + var listSerializer = new SpacetimeDB.BSATN.List(); + var listValue = global::System.Linq.Enumerable.ToList(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'demo_view': " + e); + throw; + } + } +} + +namespace SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles +{ + public sealed class DemoTableReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal DemoTableReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class IdIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.DemoTableReadOnly, + global::DemoTable, + int, + SpacetimeDB.BSATN.I32 + > + { + internal IdIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable_Id_idx_btree" + ) + ) { } + + public global::DemoTable? Find(int key) => FindSingle(key); + } + + public IdIndex Id => new(); + + public sealed class ByIdIndex + : global::SpacetimeDB.Internal.ReadOnlyIndexBase + { + internal ByIdIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable_Id_idx_btree" + ) + ) { } + + public IEnumerable Filter(int Id) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds( + Id + ) + ); + + public IEnumerable Filter(global::SpacetimeDB.Bound Id) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds( + Id + ) + ); + } + + public ByIdIndex ById => new(); + } +} + +#if !NET10_0_OR_GREATER +namespace SpacetimeDB.Internal +{ + public sealed partial class LocalReadOnly + { + public global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.DemoTableReadOnly DemoTable => + new(); + } +} +#endif + +static class ModuleRegistration +{ + // Module host calls are single-threaded in Wasm today, so the generated + // entrypoints reuse buffers across calls to avoid per-invocation allocation. + private static byte[] reducerArgsBuffer = new byte[0x10_000]; + private static byte[] procedureArgsBuffer = new byte[0x10_000]; + private static byte[] httpRequestBuffer = new byte[0x10_000]; + private static byte[] httpRequestBodyBuffer = new byte[0x10_000]; + private static byte[] viewArgsBuffer = new byte[0x10_000]; + private static byte[] anonymousViewArgsBuffer = new byte[0x10_000]; + + sealed class DemoReducer : SpacetimeDB.Internal.IReducer + { + private static readonly SpacetimeDB.BSATN.I32 valueRW = new(); + + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(DemoReducer), + Params: [new("value", valueRW.GetAlgebraicType(registrar))], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => null; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + Reducers.DemoReducer((SpacetimeDB.ReducerContext)ctx, valueRW.Read(reader)); + } + } + + sealed class DemoProcedure : SpacetimeDB.Internal.IProcedure + { + public SpacetimeDB.Internal.RawProcedureDefV10 MakeProcedureDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(DemoProcedure), + Params: [], + ReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable + ); + + public static byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) + { + Reducers.DemoProcedure((SpacetimeDB.ProcedureContext)ctx); + return System.Array.Empty(); + } + } + + public static List ToListOrEmpty(T? value) + where T : struct => value is null ? new List() : new List { value.Value }; + + public static List ToListOrEmpty(T? value) + where T : class => value is null ? new List() : new List { value }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + // In AOT mode we're building a library. + // Main method won't be called automatically, so we need to export it as a preinit function. + [UnmanagedCallersOnly(EntryPoint = "__preinit__10_init_csharp")] +#else + // Prevent trimming of FFI exports that are invoked from C and not visible to C# trimmer. + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, typeof(ModuleRegistration))] +#endif + public static void Main() => Initialize(); + + internal static void Initialize() + { +#if !NET10_0_OR_GREATER + SpacetimeDB.Internal.Module.SetReducerContextConstructor( + (identity, connectionId, random, time) => + new SpacetimeDB.ReducerContext(identity, connectionId, random, time) + ); + SpacetimeDB.Internal.Module.SetViewContextConstructor( + identity => new SpacetimeDB.ViewContext( + identity, + new SpacetimeDB.Internal.LocalReadOnly() + ) + ); + SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor(() => + new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly()) + ); + SpacetimeDB.Internal.Module.SetProcedureContextConstructor( + (identity, connectionId, random, time) => + new SpacetimeDB.ProcedureContext(identity, connectionId, random, time) + ); + SpacetimeDB.Internal.Module.SetHandlerContextConstructor( + (random, time) => new SpacetimeDB.HandlerContext(random, time) + ); +#endif + +#if NET10_0_OR_GREATER + global::SpacetimeDB.Internal.Module.InstallNamespaces( + new global::SpacetimeDB.Internal.NamespaceRegistry( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + new global::System.Collections.Generic.KeyValuePair[] { } + ) + ); + global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Register( + global::SpacetimeDB.Internal.Module.RootBuilder + ); +#else + Register(global::SpacetimeDB.Internal.Module.RootBuilder); +#endif + } + + internal static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null + ) + { + // HTTP routes retain the root routing API even for mounted modules. + httpBuilder ??= builder; + builder.SetCaseConversionPolicy(SpacetimeDB.CaseConversionPolicy.SnakeCase); + builder.RegisterExplicitTableName("DemoTable", "canonical_table"); + builder.RegisterExplicitFunctionName("DemoReducer", "canonical_reducer"); + builder.RegisterExplicitFunctionName("DemoProcedure", "canonical_procedure"); + builder.RegisterExplicitFunctionName("demo_view", "canonical_view"); + builder.RegisterExplicitIndexName("DemoTable_Id_idx_btree", "canonical_index"); + var __memoryStream = new MemoryStream(); + var __writer = new BinaryWriter(__memoryStream); + + builder.RegisterReducer(); + builder.RegisterProcedure(); + + // IMPORTANT: The order in which we register views matters. + // It must correspond to the order in which we call `GenerateDispatcherClass`. + // See the comment on `GenerateDispatcherClass` for more explanation. + builder.RegisterView(); + + builder.RegisterTable< + global::DemoTable, + global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.DemoTable + >(); + } + + // Export entrypoints live in generated module code so all build modes can + // dispatch directly to concrete generated functions. +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__describe_module__")] +#endif + public static void __describe_module__(SpacetimeDB.Internal.BytesSink d) => + SpacetimeDB.Internal.Module.__describe_module__(d); + + private static SpacetimeDB.Internal.Errno __call_reducer_0( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + DemoReducer.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_procedure_0( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink result_sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateProcedureContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref procedureArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + var bytes = DemoProcedure.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "procedure arguments"); + SpacetimeDB.Internal.Module.WriteBytes(result_sink, bytes); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking procedure: {e}"); + throw; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_0( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = demo_viewViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_reducer__")] +#endif + public static SpacetimeDB.Internal.Errno __call_reducer__( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ReducerCount + ) + return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalReducer( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ReducerCount; + return SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ); +#else + return CallLocalReducer( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) => + id switch + { + 0 => __call_reducer_0( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + _ => SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ), + }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_procedure__")] +#endif + public static SpacetimeDB.Internal.Errno __call_procedure__( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink result_sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ProcedureCount + ) + return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalProcedure( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ProcedureCount; + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); +#else + return CallLocalProcedure( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink result_sink + ) => + id switch + { + 0 => __call_procedure_0( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ), + _ => throw new System.ArgumentOutOfRangeException( + nameof(id), + id, + "Unknown procedure id" + ), + }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_http_handler__")] +#endif + public static SpacetimeDB.Internal.Errno __call_http_handler__( + int id, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource request, + SpacetimeDB.Internal.BytesSource request_body, + SpacetimeDB.Internal.BytesSink response_sink, + SpacetimeDB.Internal.BytesSink response_body_sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .HttpHandlerCount + ) + return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalHttpHandler( + localId, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .HttpHandlerCount; + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); +#else + return CallLocalHttpHandler( + id, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource request, + SpacetimeDB.Internal.BytesSource request_body, + SpacetimeDB.Internal.BytesSink response_sink, + SpacetimeDB.Internal.BytesSink response_body_sink + ) => + id switch + { + _ => throw new System.ArgumentOutOfRangeException( + nameof(id), + id, + "Unknown HTTP handler id" + ), + }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_view__")] +#endif + public static SpacetimeDB.Internal.Errno __call_view__( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return UnknownViewId(id); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ViewCount + ) + return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalView( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + args, + sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ViewCount; + return UnknownViewId(id); +#else + return CallLocalView(id, sender_0, sender_1, sender_2, sender_3, args, sink); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) => + id switch + { + 0 => __call_view_0(sender_0, sender_1, sender_2, sender_3, args, sink), + _ => UnknownViewId(id), + }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_view_anon__")] +#endif + public static SpacetimeDB.Internal.Errno __call_view_anon__( + int id, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return UnknownAnonymousViewId(id); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .AnonymousViewCount + ) + return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalAnonymousView( + localId, + args, + sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .AnonymousViewCount; + return UnknownAnonymousViewId(id); +#else + return CallLocalAnonymousView(id, args, sink); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) => + id switch + { + _ => UnknownAnonymousViewId(id), + }; + + private static SpacetimeDB.Internal.Errno UnknownViewId(int id) + { + SpacetimeDB.Log.Error($"Unknown view id: {id}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + + private static SpacetimeDB.Internal.Errno UnknownAnonymousViewId(int id) + { + SpacetimeDB.Log.Error($"Unknown anonymous view id: {id}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } +} + +#pragma warning restore STDB_UNSTABLE +#pragma warning restore CS0436 diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoProcedure.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoProcedure.verified.cs new file mode 100644 index 00000000000..8be427ec77d --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoProcedure.verified.cs @@ -0,0 +1,21 @@ +//HintName: Reducers.DemoProcedure.cs +// +#nullable enable + +partial class Reducers +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateDemoProcedure() + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.ProcedureExtensions.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "canonical_procedure" + ), + stream + ); + } +} // Reducers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoReducer.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoReducer.verified.cs new file mode 100644 index 00000000000..a907e229d4a --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoReducer.verified.cs @@ -0,0 +1,21 @@ +//HintName: Reducers.DemoReducer.cs +// +#nullable enable + +partial class Reducers +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateDemoReducer(int value) + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new SpacetimeDB.BSATN.I32().Write(writer, value); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "canonical_reducer" + ), + stream + ); + } +} // Reducers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Type#DemoType.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Type#DemoType.verified.cs index 8c54a028122..e51b981b009 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Type#DemoType.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Type#DemoType.verified.cs @@ -44,7 +44,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( new SpacetimeDB.BSATN.AggregateElement[] { - new("A", ARW.GetAlgebraicType(registrar)) + new("A", ARW.GetAlgebraicType(registrar)), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#BTreeMultiColumn.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#BTreeMultiColumn.verified.cs index f3bef07e88c..6b55693551c 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#BTreeMultiColumn.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#BTreeMultiColumn.verified.cs @@ -55,7 +55,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar { new("X", XRW.GetAlgebraicType(registrar)), new("Y", YRW.GetAlgebraicType(registrar)), - new("Z", ZRW.GetAlgebraicType(registrar)) + new("Z", ZRW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#BTreeViews.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#BTreeViews.verified.cs index 4f2ba4e758e..c31ba82463d 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#BTreeViews.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#BTreeViews.verified.cs @@ -56,7 +56,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new("Id", IdRW.GetAlgebraicType(registrar)), new("X", XRW.GetAlgebraicType(registrar)), new("Y", YRW.GetAlgebraicType(registrar)), - new("Faction", FactionRW.GetAlgebraicType(registrar)) + new("Faction", FactionRW.GetAlgebraicType(registrar)), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs index 95bbf9c0516..3334192d387 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs @@ -1,20 +1,28 @@ //HintName: FFI.cs // #nullable enable -// The runtime already defines SpacetimeDB.Internal.LocalReadOnly in Runtime\Internal\Module.cs as an empty partial type. -// This is needed so every module build doesn't generate a full LocalReadOnly type, but just adds on to the existing. -// We extend it here with generated table accessors, and just need to suppress the duplicate-type warning. +// .NET 8 generates a module-local LocalReadOnly which shadows the runtime shell. #pragma warning disable CS0436 #pragma warning disable STDB_UNSTABLE +#if NET10_0_OR_GREATER +global using SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C; +#endif using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Internal = SpacetimeDB.Internal; using TxContext = SpacetimeDB.Internal.TxContext; +#if NET10_0_OR_GREATER +[assembly: global::SpacetimeDB.ModuleDescriptorAttribute( + typeof(global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor) +)] + +#endif namespace SpacetimeDB { +#if !NET10_0_OR_GREATER internal readonly struct BTreeMultiColumnCols { public readonly global::SpacetimeDB.Col X; @@ -488,9 +496,11 @@ public readonly partial struct QueryBuilder new SendMessageTimerIxCols("SendMessageTimer") ); } +#endif public static class Handlers { } +#if !NET10_0_OR_GREATER public sealed record ReducerContext : DbContext, Internal.IReducerContext { public global::SpacetimeDB.ModuleEnvironment Env => default; @@ -715,45 +725,888 @@ internal HandlerTxContext(Internal.TxContext inner) public new Local Db => (Local)base.Db; } - public sealed class Local : global::SpacetimeDB.LocalBase + public sealed class Local : global::SpacetimeDB.LocalBase + { + internal global::SpacetimeDB.Internal.TableHandles.BTreeMultiColumn BTreeMultiColumn => + new(); + internal global::SpacetimeDB.Internal.TableHandles.BTreeViews BTreeViews => new(); + public global::SpacetimeDB.Internal.TableHandles.MultiTable1 MultiTable1 => new(); + public global::SpacetimeDB.Internal.TableHandles.MultiTable2 MultiTable2 => new(); + public global::SpacetimeDB.Internal.TableHandles.PrivateTable PrivateTable => new(); + public global::SpacetimeDB.Internal.TableHandles.PublicTable PublicTable => new(); + internal global::SpacetimeDB.Internal.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => + new(); + public global::SpacetimeDB.Internal.TableHandles.SendMessageTimer SendMessageTimer => new(); + } + + public sealed record ViewContext : DbContext, Internal.IViewContext + { + public Identity Sender { get; } + + public global::SpacetimeDB.ModuleEnvironment Env => default; + public QueryBuilder From => default; + + internal ViewContext(Identity sender, Internal.LocalReadOnly db) + : base(db) + { + Sender = sender; + } + } + + public sealed record AnonymousViewContext + : DbContext, + Internal.IAnonymousViewContext + { + public global::SpacetimeDB.ModuleEnvironment Env => default; + public QueryBuilder From => default; + + internal AnonymousViewContext(Internal.LocalReadOnly db) + : base(db) { } + } +#endif +} + +#if NET10_0_OR_GREATER +namespace SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +{ + public static partial class AssemblyDescriptor + { + public const string LifecycleReducers = "Timers.Init (Init)"; + public const int ReducerCount = 6; + public const int ProcedureCount = 0; + public const int HttpHandlerCount = 0; + public const int ViewCount = 2; + public const int AnonymousViewCount = 1; + + public static global::SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink error + ) => + global::ModuleRegistration.CallLocalReducer( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink result_sink + ) => + global::ModuleRegistration.CallLocalProcedure( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource request, + global::SpacetimeDB.Internal.BytesSource request_body, + global::SpacetimeDB.Internal.BytesSink response_sink, + global::SpacetimeDB.Internal.BytesSink response_body_sink + ) => + global::ModuleRegistration.CallLocalHttpHandler( + id, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => + global::ModuleRegistration.CallLocalView( + id, + sender_0, + sender_1, + sender_2, + sender_3, + args, + sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => global::ModuleRegistration.CallLocalAnonymousView(id, args, sink); + + public static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null + ) => global::ModuleRegistration.Register(builder, httpBuilder); + + public readonly struct Tables + { + internal global::SpacetimeDB.Internal.TableHandles.BTreeMultiColumn BTreeMultiColumn => + new(); + internal global::SpacetimeDB.Internal.TableHandles.BTreeViews BTreeViews => new(); + public global::SpacetimeDB.Internal.TableHandles.MultiTable1 MultiTable1 => new(); + public global::SpacetimeDB.Internal.TableHandles.MultiTable2 MultiTable2 => new(); + public global::SpacetimeDB.Internal.TableHandles.PrivateTable PrivateTable => new(); + public global::SpacetimeDB.Internal.TableHandles.PublicTable PublicTable => new(); + internal global::SpacetimeDB.Internal.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => + new(); + public global::SpacetimeDB.Internal.TableHandles.SendMessageTimer SendMessageTimer => + new(); + } + + public readonly struct ReadOnlyTables + { + internal global::SpacetimeDB.Internal.ViewHandles.BTreeMultiColumnReadOnly BTreeMultiColumn => + new(); + internal global::SpacetimeDB.Internal.ViewHandles.BTreeViewsReadOnly BTreeViews => + new(); + public global::SpacetimeDB.Internal.ViewHandles.MultiTable1ReadOnly MultiTable1 => + new(); + public global::SpacetimeDB.Internal.ViewHandles.MultiTable2ReadOnly MultiTable2 => + new(); + public global::SpacetimeDB.Internal.ViewHandles.PrivateTableReadOnly PrivateTable => + new(); + public global::SpacetimeDB.Internal.ViewHandles.PublicTableReadOnly PublicTable => + new(); + internal global::SpacetimeDB.Internal.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly RegressionMultipleUniqueIndexesHadSameName => + new(); + public global::SpacetimeDB.Internal.ViewHandles.SendMessageTimerReadOnly SendMessageTimer => + new(); + } + + public readonly partial struct Queries { } + } + + public static class LocalTableExtensions + { + extension(global::SpacetimeDB.Local db) + { + internal global::SpacetimeDB.Internal.TableHandles.BTreeMultiColumn BTreeMultiColumn => + new(); + internal global::SpacetimeDB.Internal.TableHandles.BTreeViews BTreeViews => new(); + public global::SpacetimeDB.Internal.TableHandles.MultiTable1 MultiTable1 => new(); + public global::SpacetimeDB.Internal.TableHandles.MultiTable2 MultiTable2 => new(); + public global::SpacetimeDB.Internal.TableHandles.PrivateTable PrivateTable => new(); + public global::SpacetimeDB.Internal.TableHandles.PublicTable PublicTable => new(); + internal global::SpacetimeDB.Internal.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => + new(); + public global::SpacetimeDB.Internal.TableHandles.SendMessageTimer SendMessageTimer => + new(); + } + } + + public static class ReadOnlyTableExtensions + { + extension(global::SpacetimeDB.Internal.LocalReadOnly db) + { + internal global::SpacetimeDB.Internal.ViewHandles.BTreeMultiColumnReadOnly BTreeMultiColumn => + new(); + internal global::SpacetimeDB.Internal.ViewHandles.BTreeViewsReadOnly BTreeViews => + new(); + public global::SpacetimeDB.Internal.ViewHandles.MultiTable1ReadOnly MultiTable1 => + new(); + public global::SpacetimeDB.Internal.ViewHandles.MultiTable2ReadOnly MultiTable2 => + new(); + public global::SpacetimeDB.Internal.ViewHandles.PrivateTableReadOnly PrivateTable => + new(); + public global::SpacetimeDB.Internal.ViewHandles.PublicTableReadOnly PublicTable => + new(); + internal global::SpacetimeDB.Internal.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly RegressionMultipleUniqueIndexesHadSameName => + new(); + public global::SpacetimeDB.Internal.ViewHandles.SendMessageTimerReadOnly SendMessageTimer => + new(); + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) { } + } + + internal readonly struct BTreeMultiColumnCols + { + public readonly global::SpacetimeDB.Col X; + public readonly global::SpacetimeDB.Col Y; + public readonly global::SpacetimeDB.Col Z; + + internal BTreeMultiColumnCols(global::SpacetimeDB.SqlTableName tableName) + { + X = new global::SpacetimeDB.Col(tableName, "X"); + Y = new global::SpacetimeDB.Col(tableName, "Y"); + Z = new global::SpacetimeDB.Col(tableName, "Z"); + } + } + + internal readonly struct BTreeMultiColumnIxCols + { + public readonly global::SpacetimeDB.IxCol X; + public readonly global::SpacetimeDB.IxCol Y; + public readonly global::SpacetimeDB.IxCol Z; + + internal BTreeMultiColumnIxCols(global::SpacetimeDB.SqlTableName tableName) + { + X = new global::SpacetimeDB.IxCol(tableName, "X"); + Y = new global::SpacetimeDB.IxCol(tableName, "Y"); + Z = new global::SpacetimeDB.IxCol(tableName, "Z"); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + internal global::SpacetimeDB.Table< + global::BTreeMultiColumn, + BTreeMultiColumnCols, + BTreeMultiColumnIxCols + > BTreeMultiColumn() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeMultiColumn" + ); + return new( + tableName, + new BTreeMultiColumnCols(tableName), + new BTreeMultiColumnIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + internal global::SpacetimeDB.Table< + global::BTreeMultiColumn, + BTreeMultiColumnCols, + BTreeMultiColumnIxCols + > BTreeMultiColumn() => new AssemblyDescriptor.Queries().BTreeMultiColumn(); + } + } + + internal readonly struct BTreeViewsCols + { + public readonly global::SpacetimeDB.Col Id; + public readonly global::SpacetimeDB.Col X; + public readonly global::SpacetimeDB.Col Y; + public readonly global::SpacetimeDB.Col Faction; + + internal BTreeViewsCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.Col( + tableName, + "Id" + ); + X = new global::SpacetimeDB.Col(tableName, "X"); + Y = new global::SpacetimeDB.Col(tableName, "Y"); + Faction = new global::SpacetimeDB.Col(tableName, "Faction"); + } + } + + internal readonly struct BTreeViewsIxCols + { + public readonly global::SpacetimeDB.IxCol Id; + public readonly global::SpacetimeDB.IxCol X; + public readonly global::SpacetimeDB.IxCol Y; + public readonly global::SpacetimeDB.IxCol Faction; + + internal BTreeViewsIxCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.IxCol( + tableName, + "Id" + ); + X = new global::SpacetimeDB.IxCol(tableName, "X"); + Y = new global::SpacetimeDB.IxCol(tableName, "Y"); + Faction = new global::SpacetimeDB.IxCol( + tableName, + "Faction" + ); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + internal global::SpacetimeDB.Table< + global::BTreeViews, + BTreeViewsCols, + BTreeViewsIxCols + > BTreeViews() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews" + ); + return new( + tableName, + new BTreeViewsCols(tableName), + new BTreeViewsIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + internal global::SpacetimeDB.Table< + global::BTreeViews, + BTreeViewsCols, + BTreeViewsIxCols + > BTreeViews() => new AssemblyDescriptor.Queries().BTreeViews(); + } + } + + public readonly struct MultiTable1Cols + { + public readonly global::SpacetimeDB.Col Name; + public readonly global::SpacetimeDB.Col Foo; + public readonly global::SpacetimeDB.Col Bar; + + internal MultiTable1Cols(global::SpacetimeDB.SqlTableName tableName) + { + Name = new global::SpacetimeDB.Col(tableName, "Name"); + Foo = new global::SpacetimeDB.Col(tableName, "Foo"); + Bar = new global::SpacetimeDB.Col(tableName, "Bar"); + } + } + + public readonly struct MultiTable1IxCols + { + public readonly global::SpacetimeDB.IxCol Name; + public readonly global::SpacetimeDB.IxCol Foo; + + internal MultiTable1IxCols(global::SpacetimeDB.SqlTableName tableName) + { + Name = new global::SpacetimeDB.IxCol(tableName, "Name"); + Foo = new global::SpacetimeDB.IxCol(tableName, "Foo"); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::MultiTableRow, + MultiTable1Cols, + MultiTable1IxCols + > MultiTable1() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1" + ); + return new( + tableName, + new MultiTable1Cols(tableName), + new MultiTable1IxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::MultiTableRow, + MultiTable1Cols, + MultiTable1IxCols + > MultiTable1() => new AssemblyDescriptor.Queries().MultiTable1(); + } + } + + public readonly struct MultiTable2Cols + { + public readonly global::SpacetimeDB.Col Name; + public readonly global::SpacetimeDB.Col Foo; + public readonly global::SpacetimeDB.Col Bar; + + internal MultiTable2Cols(global::SpacetimeDB.SqlTableName tableName) + { + Name = new global::SpacetimeDB.Col(tableName, "Name"); + Foo = new global::SpacetimeDB.Col(tableName, "Foo"); + Bar = new global::SpacetimeDB.Col(tableName, "Bar"); + } + } + + public readonly struct MultiTable2IxCols + { + internal MultiTable2IxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::MultiTableRow, + MultiTable2Cols, + MultiTable2IxCols + > MultiTable2() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable2" + ); + return new( + tableName, + new MultiTable2Cols(tableName), + new MultiTable2IxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::MultiTableRow, + MultiTable2Cols, + MultiTable2IxCols + > MultiTable2() => new AssemblyDescriptor.Queries().MultiTable2(); + } + } + + public readonly struct PrivateTableCols + { + internal PrivateTableCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public readonly struct PrivateTableIxCols + { + internal PrivateTableIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::PrivateTable, + PrivateTableCols, + PrivateTableIxCols + > PrivateTable() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PrivateTable" + ); + return new( + tableName, + new PrivateTableCols(tableName), + new PrivateTableIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::PrivateTable, + PrivateTableCols, + PrivateTableIxCols + > PrivateTable() => new AssemblyDescriptor.Queries().PrivateTable(); + } + } + + public readonly struct PublicTableCols + { + public readonly global::SpacetimeDB.Col Id; + public readonly global::SpacetimeDB.Col ByteField; + public readonly global::SpacetimeDB.Col UshortField; + public readonly global::SpacetimeDB.Col UintField; + public readonly global::SpacetimeDB.Col UlongField; + public readonly global::SpacetimeDB.Col UInt128Field; + public readonly global::SpacetimeDB.Col U128Field; + public readonly global::SpacetimeDB.Col U256Field; + public readonly global::SpacetimeDB.Col SbyteField; + public readonly global::SpacetimeDB.Col ShortField; + public readonly global::SpacetimeDB.Col IntField; + public readonly global::SpacetimeDB.Col LongField; + public readonly global::SpacetimeDB.Col Int128Field; + public readonly global::SpacetimeDB.Col I128Field; + public readonly global::SpacetimeDB.Col I256Field; + public readonly global::SpacetimeDB.Col BoolField; + public readonly global::SpacetimeDB.Col FloatField; + public readonly global::SpacetimeDB.Col DoubleField; + public readonly global::SpacetimeDB.Col StringField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + SpacetimeDB.Identity + > IdentityField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + SpacetimeDB.ConnectionId + > ConnectionIdField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + CustomStruct + > CustomStructField; + public readonly global::SpacetimeDB.Col CustomClassField; + public readonly global::SpacetimeDB.Col CustomEnumField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + CustomTaggedEnum + > CustomTaggedEnumField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + System.Collections.Generic.List + > ListField; + public readonly global::SpacetimeDB.Col NullableValueField; + public readonly global::SpacetimeDB.Col NullableReferenceField; + + internal PublicTableCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "Id"); + ByteField = new global::SpacetimeDB.Col( + tableName, + "ByteField" + ); + UshortField = new global::SpacetimeDB.Col( + tableName, + "UshortField" + ); + UintField = new global::SpacetimeDB.Col( + tableName, + "UintField" + ); + UlongField = new global::SpacetimeDB.Col( + tableName, + "UlongField" + ); + UInt128Field = new global::SpacetimeDB.Col( + tableName, + "UInt128Field" + ); + U128Field = new global::SpacetimeDB.Col( + tableName, + "U128Field" + ); + U256Field = new global::SpacetimeDB.Col( + tableName, + "U256Field" + ); + SbyteField = new global::SpacetimeDB.Col( + tableName, + "SbyteField" + ); + ShortField = new global::SpacetimeDB.Col( + tableName, + "ShortField" + ); + IntField = new global::SpacetimeDB.Col(tableName, "IntField"); + LongField = new global::SpacetimeDB.Col( + tableName, + "LongField" + ); + Int128Field = new global::SpacetimeDB.Col( + tableName, + "Int128Field" + ); + I128Field = new global::SpacetimeDB.Col( + tableName, + "I128Field" + ); + I256Field = new global::SpacetimeDB.Col( + tableName, + "I256Field" + ); + BoolField = new global::SpacetimeDB.Col( + tableName, + "BoolField" + ); + FloatField = new global::SpacetimeDB.Col( + tableName, + "FloatField" + ); + DoubleField = new global::SpacetimeDB.Col( + tableName, + "DoubleField" + ); + StringField = new global::SpacetimeDB.Col( + tableName, + "StringField" + ); + IdentityField = new global::SpacetimeDB.Col( + tableName, + "IdentityField" + ); + ConnectionIdField = new global::SpacetimeDB.Col< + global::PublicTable, + SpacetimeDB.ConnectionId + >(tableName, "ConnectionIdField"); + CustomStructField = new global::SpacetimeDB.Col( + tableName, + "CustomStructField" + ); + CustomClassField = new global::SpacetimeDB.Col( + tableName, + "CustomClassField" + ); + CustomEnumField = new global::SpacetimeDB.Col( + tableName, + "CustomEnumField" + ); + CustomTaggedEnumField = new global::SpacetimeDB.Col< + global::PublicTable, + CustomTaggedEnum + >(tableName, "CustomTaggedEnumField"); + ListField = new global::SpacetimeDB.Col< + global::PublicTable, + System.Collections.Generic.List + >(tableName, "ListField"); + NullableValueField = new global::SpacetimeDB.Col( + tableName, + "NullableValueField" + ); + NullableReferenceField = new global::SpacetimeDB.Col( + tableName, + "NullableReferenceField" + ); + } + } + + public readonly struct PublicTableIxCols + { + public readonly global::SpacetimeDB.IxCol Id; + + internal PublicTableIxCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "Id"); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::PublicTable, + PublicTableCols, + PublicTableIxCols + > PublicTable() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PublicTable" + ); + return new( + tableName, + new PublicTableCols(tableName), + new PublicTableIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::PublicTable, + PublicTableCols, + PublicTableIxCols + > PublicTable() => new AssemblyDescriptor.Queries().PublicTable(); + } + } + + internal readonly struct RegressionMultipleUniqueIndexesHadSameNameCols + { + public readonly global::SpacetimeDB.Col< + global::RegressionMultipleUniqueIndexesHadSameName, + uint + > Unique1; + public readonly global::SpacetimeDB.Col< + global::RegressionMultipleUniqueIndexesHadSameName, + uint + > Unique2; + + internal RegressionMultipleUniqueIndexesHadSameNameCols( + global::SpacetimeDB.SqlTableName tableName + ) + { + Unique1 = new global::SpacetimeDB.Col< + global::RegressionMultipleUniqueIndexesHadSameName, + uint + >(tableName, "Unique1"); + Unique2 = new global::SpacetimeDB.Col< + global::RegressionMultipleUniqueIndexesHadSameName, + uint + >(tableName, "Unique2"); + } + } + + internal readonly struct RegressionMultipleUniqueIndexesHadSameNameIxCols + { + internal RegressionMultipleUniqueIndexesHadSameNameIxCols( + global::SpacetimeDB.SqlTableName tableName + ) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + internal global::SpacetimeDB.Table< + global::RegressionMultipleUniqueIndexesHadSameName, + RegressionMultipleUniqueIndexesHadSameNameCols, + RegressionMultipleUniqueIndexesHadSameNameIxCols + > RegressionMultipleUniqueIndexesHadSameName() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName" + ); + return new( + tableName, + new RegressionMultipleUniqueIndexesHadSameNameCols(tableName), + new RegressionMultipleUniqueIndexesHadSameNameIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + internal global::SpacetimeDB.Table< + global::RegressionMultipleUniqueIndexesHadSameName, + RegressionMultipleUniqueIndexesHadSameNameCols, + RegressionMultipleUniqueIndexesHadSameNameIxCols + > RegressionMultipleUniqueIndexesHadSameName() => + new AssemblyDescriptor.Queries().RegressionMultipleUniqueIndexesHadSameName(); + } + } + + public readonly struct SendMessageTimerCols + { + public readonly global::SpacetimeDB.Col ScheduledId; + public readonly global::SpacetimeDB.Col< + global::Timers.SendMessageTimer, + SpacetimeDB.ScheduleAt + > ScheduledAt; + public readonly global::SpacetimeDB.Col Text; + + internal SendMessageTimerCols(global::SpacetimeDB.SqlTableName tableName) + { + ScheduledId = new global::SpacetimeDB.Col( + tableName, + "ScheduledId" + ); + ScheduledAt = new global::SpacetimeDB.Col< + global::Timers.SendMessageTimer, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduledAt"); + Text = new global::SpacetimeDB.Col( + tableName, + "Text" + ); + } + } + + public readonly struct SendMessageTimerIxCols { - internal global::SpacetimeDB.Internal.TableHandles.BTreeMultiColumn BTreeMultiColumn => - new(); - internal global::SpacetimeDB.Internal.TableHandles.BTreeViews BTreeViews => new(); - public global::SpacetimeDB.Internal.TableHandles.MultiTable1 MultiTable1 => new(); - public global::SpacetimeDB.Internal.TableHandles.MultiTable2 MultiTable2 => new(); - public global::SpacetimeDB.Internal.TableHandles.PrivateTable PrivateTable => new(); - public global::SpacetimeDB.Internal.TableHandles.PublicTable PublicTable => new(); - internal global::SpacetimeDB.Internal.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => - new(); - public global::SpacetimeDB.Internal.TableHandles.SendMessageTimer SendMessageTimer => new(); + public readonly global::SpacetimeDB.IxCol< + global::Timers.SendMessageTimer, + ulong + > ScheduledId; + + internal SendMessageTimerIxCols(global::SpacetimeDB.SqlTableName tableName) + { + ScheduledId = new global::SpacetimeDB.IxCol( + tableName, + "ScheduledId" + ); + } } - public sealed record ViewContext : DbContext, Internal.IViewContext + public static partial class AssemblyDescriptor { - public Identity Sender { get; } - - public global::SpacetimeDB.ModuleEnvironment Env => default; - public QueryBuilder From => default; - - internal ViewContext(Identity sender, Internal.LocalReadOnly db) - : base(db) + public readonly partial struct Queries { - Sender = sender; + public global::SpacetimeDB.Table< + global::Timers.SendMessageTimer, + SendMessageTimerCols, + SendMessageTimerIxCols + > SendMessageTimer() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "SendMessageTimer" + ); + return new( + tableName, + new SendMessageTimerCols(tableName), + new SendMessageTimerIxCols(tableName) + ); + } } } - public sealed record AnonymousViewContext - : DbContext, - Internal.IAnonymousViewContext + public static partial class QueryTableExtensions { - public global::SpacetimeDB.ModuleEnvironment Env => default; - public QueryBuilder From => default; - - internal AnonymousViewContext(Internal.LocalReadOnly db) - : base(db) { } + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::Timers.SendMessageTimer, + SendMessageTimerCols, + SendMessageTimerIxCols + > SendMessageTimer() => new AssemblyDescriptor.Queries().SendMessageTimer(); + } } } +#endif namespace SpacetimeDB.Internal.TableHandles { @@ -782,7 +1635,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "BTreeMultiColumn_X_Y_Z_idx_btree", AccessorName: "Location", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0, 1, 2]) - ) + ), ], Constraints: [], Sequences: [], @@ -980,14 +1833,14 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "BTreeViews_Faction_idx_btree", AccessorName: "Faction", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([3]) - ) + ), ], Constraints: [ global::SpacetimeDB.Internal.ITableView< BTreeViews, global::BTreeViews - >.MakeUniqueConstraint(0) + >.MakeUniqueConstraint(0), ], Sequences: [], TableType: SpacetimeDB.Internal.TableType.User, @@ -1020,7 +1873,7 @@ public ulong Clear() => global::SpacetimeDB.Internal.ITableView.DoClear(); internal sealed class IdUniqueIndex - : UniqueIndex< + : global::SpacetimeDB.Internal.UniqueIndex< BTreeViews, global::BTreeViews, SpacetimeDB.Identity, @@ -1171,21 +2024,21 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "MultiTable1_Name_idx_btree", AccessorName: "Name", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) + ), ], Constraints: [ global::SpacetimeDB.Internal.ITableView< MultiTable1, global::MultiTableRow - >.MakeUniqueConstraint(1) + >.MakeUniqueConstraint(1), ], Sequences: [ global::SpacetimeDB.Internal.ITableView< MultiTable1, global::MultiTableRow - >.MakeSequence(1) + >.MakeSequence(1), ], TableType: SpacetimeDB.Internal.TableType.User, TableAccess: SpacetimeDB.Internal.TableAccess.Public, @@ -1221,7 +2074,12 @@ public ulong Clear() => global::SpacetimeDB.Internal.ITableView.DoClear(); public sealed class FooUniqueIndex - : UniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + MultiTable1, + global::MultiTableRow, + uint, + SpacetimeDB.BSATN.U32 + > { internal FooUniqueIndex() : base("MultiTable1_Foo_idx_btree") { } @@ -1302,21 +2160,21 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "MultiTable2_Bar_idx_btree", AccessorName: "Bar", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([2]) - ) + ), ], Constraints: [ global::SpacetimeDB.Internal.ITableView< MultiTable2, global::MultiTableRow - >.MakeUniqueConstraint(2) + >.MakeUniqueConstraint(2), ], Sequences: [ global::SpacetimeDB.Internal.ITableView< MultiTable2, global::MultiTableRow - >.MakeSequence(1) + >.MakeSequence(1), ], TableType: SpacetimeDB.Internal.TableType.User, TableAccess: SpacetimeDB.Internal.TableAccess.Private, @@ -1352,7 +2210,12 @@ public ulong Clear() => global::SpacetimeDB.Internal.ITableView.DoClear(); public sealed class BarUniqueIndex - : UniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + MultiTable2, + global::MultiTableRow, + uint, + SpacetimeDB.BSATN.U32 + > { internal BarUniqueIndex() : base("MultiTable2_Bar_idx_btree") { } @@ -1451,21 +2314,21 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "PublicTable_Id_idx_btree", AccessorName: "Id", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) + ), ], Constraints: [ global::SpacetimeDB.Internal.ITableView< PublicTable, global::PublicTable - >.MakeUniqueConstraint(0) + >.MakeUniqueConstraint(0), ], Sequences: [ global::SpacetimeDB.Internal.ITableView< PublicTable, global::PublicTable - >.MakeSequence(0) + >.MakeSequence(0), ], TableType: SpacetimeDB.Internal.TableType.User, TableAccess: SpacetimeDB.Internal.TableAccess.Public, @@ -1497,7 +2360,12 @@ public ulong Clear() => global::SpacetimeDB.Internal.ITableView.DoClear(); public sealed class IdUniqueIndex - : UniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + PublicTable, + global::PublicTable, + int, + SpacetimeDB.BSATN.I32 + > { internal IdUniqueIndex() : base("PublicTable_Id_idx_btree") { } @@ -1548,7 +2416,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "RegressionMultipleUniqueIndexesHadSameName_Unique2_idx_btree", AccessorName: "Unique2", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) - ) + ), ], Constraints: [ @@ -1559,7 +2427,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar global::SpacetimeDB.Internal.ITableView< RegressionMultipleUniqueIndexesHadSameName, global::RegressionMultipleUniqueIndexesHadSameName - >.MakeUniqueConstraint(1) + >.MakeUniqueConstraint(1), ], Sequences: [], TableType: SpacetimeDB.Internal.TableType.User, @@ -1609,7 +2477,7 @@ public ulong Clear() => >.DoClear(); internal sealed class Unique1UniqueIndex - : UniqueIndex< + : global::SpacetimeDB.Internal.UniqueIndex< RegressionMultipleUniqueIndexesHadSameName, global::RegressionMultipleUniqueIndexesHadSameName, uint, @@ -1629,7 +2497,7 @@ internal Unique1UniqueIndex() internal Unique1UniqueIndex Unique1 => new(); internal sealed class Unique2UniqueIndex - : UniqueIndex< + : global::SpacetimeDB.Internal.UniqueIndex< RegressionMultipleUniqueIndexesHadSameName, global::RegressionMultipleUniqueIndexesHadSameName, uint, @@ -1678,21 +2546,21 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar SourceName: "SendMessageTimer_ScheduledId_idx_btree", AccessorName: "ScheduledId", Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) + ), ], Constraints: [ global::SpacetimeDB.Internal.ITableView< SendMessageTimer, global::Timers.SendMessageTimer - >.MakeUniqueConstraint(0) + >.MakeUniqueConstraint(0), ], Sequences: [ global::SpacetimeDB.Internal.ITableView< SendMessageTimer, global::Timers.SendMessageTimer - >.MakeSequence(0) + >.MakeSequence(0), ], TableType: SpacetimeDB.Internal.TableType.User, TableAccess: SpacetimeDB.Internal.TableAccess.Private, @@ -1743,7 +2611,7 @@ public ulong Clear() => >.DoClear(); public sealed class ScheduledIdUniqueIndex - : UniqueIndex< + : global::SpacetimeDB.Internal.UniqueIndex< SendMessageTimer, global::Timers.SendMessageTimer, ulong, @@ -2311,6 +3179,7 @@ internal ScheduledIdIndex() } } +#if !NET10_0_OR_GREATER namespace SpacetimeDB.Internal { public sealed partial class LocalReadOnly @@ -2328,6 +3197,7 @@ public sealed partial class LocalReadOnly new(); } } +#endif static class ModuleRegistration { @@ -2493,8 +3363,11 @@ public static List ToListOrEmpty(T? value) // Prevent trimming of FFI exports that are invoked from C and not visible to C# trimmer. [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, typeof(ModuleRegistration))] #endif - public static void Main() + public static void Main() => Initialize(); + + internal static void Initialize() { +#if !NET10_0_OR_GREATER SpacetimeDB.Internal.Module.SetReducerContextConstructor( (identity, connectionId, random, time) => new SpacetimeDB.ReducerContext(identity, connectionId, random, time) @@ -2505,8 +3378,8 @@ public static void Main() new SpacetimeDB.Internal.LocalReadOnly() ) ); - SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor( - () => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly()) + SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor(() => + new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly()) ); SpacetimeDB.Internal.Module.SetProcedureContextConstructor( (identity, connectionId, random, time) => @@ -2515,59 +3388,82 @@ public static void Main() SpacetimeDB.Internal.Module.SetHandlerContextConstructor( (random, time) => new SpacetimeDB.HandlerContext(random, time) ); +#endif + +#if NET10_0_OR_GREATER + global::SpacetimeDB.Internal.Module.InstallNamespaces( + new global::SpacetimeDB.Internal.NamespaceRegistry( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + new global::System.Collections.Generic.KeyValuePair[] { } + ) + ); + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Register( + global::SpacetimeDB.Internal.Module.RootBuilder + ); +#else + Register(global::SpacetimeDB.Internal.Module.RootBuilder); +#endif + } + + internal static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null + ) + { + // HTTP routes retain the root routing API even for mounted modules. + httpBuilder ??= builder; + var __memoryStream = new MemoryStream(); var __writer = new BinaryWriter(__memoryStream); - SpacetimeDB.Internal.Module.RegisterReducer(); - SpacetimeDB.Internal.Module.RegisterReducer(); - SpacetimeDB.Internal.Module.RegisterReducer(); - SpacetimeDB.Internal.Module.RegisterReducer(); - SpacetimeDB.Internal.Module.RegisterReducer(); - SpacetimeDB.Internal.Module.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); // IMPORTANT: The order in which we register views matters. // It must correspond to the order in which we call `GenerateDispatcherClass`. // See the comment on `GenerateDispatcherClass` for more explanation. - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterView(); - SpacetimeDB.Internal.Module.RegisterAnonymousView(); + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterAnonymousView(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::BTreeMultiColumn, - SpacetimeDB.Internal.TableHandles.BTreeMultiColumn + global::SpacetimeDB.Internal.TableHandles.BTreeMultiColumn >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::BTreeViews, - SpacetimeDB.Internal.TableHandles.BTreeViews + global::SpacetimeDB.Internal.TableHandles.BTreeViews >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::MultiTableRow, - SpacetimeDB.Internal.TableHandles.MultiTable1 + global::SpacetimeDB.Internal.TableHandles.MultiTable1 >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::MultiTableRow, - SpacetimeDB.Internal.TableHandles.MultiTable2 + global::SpacetimeDB.Internal.TableHandles.MultiTable2 >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::PrivateTable, - SpacetimeDB.Internal.TableHandles.PrivateTable + global::SpacetimeDB.Internal.TableHandles.PrivateTable >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::PublicTable, - SpacetimeDB.Internal.TableHandles.PublicTable + global::SpacetimeDB.Internal.TableHandles.PublicTable >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::RegressionMultipleUniqueIndexesHadSameName, - SpacetimeDB.Internal.TableHandles.RegressionMultipleUniqueIndexesHadSameName + global::SpacetimeDB.Internal.TableHandles.RegressionMultipleUniqueIndexesHadSameName >(); - SpacetimeDB.Internal.Module.RegisterTable< + builder.RegisterTable< global::Timers.SendMessageTimer, - SpacetimeDB.Internal.TableHandles.SendMessageTimer + global::SpacetimeDB.Internal.TableHandles.SendMessageTimer >(); - SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter( - global::Module.ALL_PUBLIC_TABLES - ); + builder.RegisterClientVisibilityFilter(global::Module.ALL_PUBLIC_TABLES); } // Export entrypoints live in generated module code so all build modes can @@ -2904,86 +3800,147 @@ public static SpacetimeDB.Internal.Errno __call_reducer__( SpacetimeDB.Timestamp timestamp, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink error + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ReducerCount + ) + return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalReducer( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ReducerCount; + return SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ); +#else + return CallLocalReducer( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error ) => id switch { - 0 - => __call_reducer_0( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - 1 - => __call_reducer_1( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - 2 - => __call_reducer_2( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - 3 - => __call_reducer_3( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - 4 - => __call_reducer_4( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - 5 - => __call_reducer_5( - sender_0, - sender_1, - sender_2, - sender_3, - conn_id_0, - conn_id_1, - timestamp, - args, - error - ), - _ - => SpacetimeDB.Internal.Module.WriteReducerError( - error, - new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") - ) + 0 => __call_reducer_0( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 1 => __call_reducer_1( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 2 => __call_reducer_2( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 3 => __call_reducer_3( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 4 => __call_reducer_4( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 5 => __call_reducer_5( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + _ => SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ), }; #if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER @@ -3000,15 +3957,76 @@ public static SpacetimeDB.Internal.Errno __call_procedure__( SpacetimeDB.Timestamp timestamp, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink result_sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ProcedureCount + ) + return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalProcedure( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ProcedureCount; + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); +#else + return CallLocalProcedure( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink result_sink ) => id switch { - _ - => throw new System.ArgumentOutOfRangeException( - nameof(id), - id, - "Unknown procedure id" - ) + _ => throw new System.ArgumentOutOfRangeException( + nameof(id), + id, + "Unknown procedure id" + ), }; #if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER @@ -3021,15 +4039,64 @@ public static SpacetimeDB.Internal.Errno __call_http_handler__( SpacetimeDB.Internal.BytesSource request_body, SpacetimeDB.Internal.BytesSink response_sink, SpacetimeDB.Internal.BytesSink response_body_sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .HttpHandlerCount + ) + return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalHttpHandler( + localId, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .HttpHandlerCount; + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); +#else + return CallLocalHttpHandler( + id, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource request, + SpacetimeDB.Internal.BytesSource request_body, + SpacetimeDB.Internal.BytesSink response_sink, + SpacetimeDB.Internal.BytesSink response_body_sink ) => id switch { - _ - => throw new System.ArgumentOutOfRangeException( - nameof(id), - id, - "Unknown HTTP handler id" - ) + _ => throw new System.ArgumentOutOfRangeException( + nameof(id), + id, + "Unknown HTTP handler id" + ), }; #if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER @@ -3043,12 +4110,57 @@ public static SpacetimeDB.Internal.Errno __call_view__( ulong sender_3, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return UnknownViewId(id); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ViewCount + ) + return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalView( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + args, + sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ViewCount; + return UnknownViewId(id); +#else + return CallLocalView(id, sender_0, sender_1, sender_2, sender_3, args, sink); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink ) => id switch { 0 => __call_view_0(sender_0, sender_1, sender_2, sender_3, args, sink), 1 => __call_view_1(sender_0, sender_1, sender_2, sender_3, args, sink), - _ => UnknownViewId(id) + _ => UnknownViewId(id), }; #if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER @@ -3058,11 +4170,48 @@ public static SpacetimeDB.Internal.Errno __call_view_anon__( int id, SpacetimeDB.Internal.BytesSource args, SpacetimeDB.Internal.BytesSink sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return UnknownAnonymousViewId(id); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .AnonymousViewCount + ) + return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalAnonymousView( + localId, + args, + sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .AnonymousViewCount; + return UnknownAnonymousViewId(id); +#else + return CallLocalAnonymousView(id, args, sink); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink ) => id switch { 0 => __call_view_anon_0(args, sink), - _ => UnknownAnonymousViewId(id) + _ => UnknownAnonymousViewId(id), }; private static SpacetimeDB.Internal.Errno UnknownViewId(int id) diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#MultiTableRow.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#MultiTableRow.verified.cs index 7a801bc3b6e..d5786199b4b 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#MultiTableRow.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#MultiTableRow.verified.cs @@ -54,7 +54,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar { new("Name", NameRW.GetAlgebraicType(registrar)), new("Foo", FooRW.GetAlgebraicType(registrar)), - new("Bar", BarRW.GetAlgebraicType(registrar)) + new("Bar", BarRW.GetAlgebraicType(registrar)), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#PublicTable.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#PublicTable.verified.cs index f30b7f9d6a6..66eb1f4dfe6 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#PublicTable.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#PublicTable.verified.cs @@ -165,7 +165,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new( "NullableReferenceField", NullableReferenceFieldRW.GetAlgebraicType(registrar) - ) + ), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#RegressionMultipleUniqueIndexesHadSameName.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#RegressionMultipleUniqueIndexesHadSameName.verified.cs index bf52d45ea00..08d5589debd 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#RegressionMultipleUniqueIndexesHadSameName.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#RegressionMultipleUniqueIndexesHadSameName.verified.cs @@ -55,7 +55,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new SpacetimeDB.BSATN.AggregateElement[] { new("Unique1", Unique1RW.GetAlgebraicType(registrar)), - new("Unique2", Unique2RW.GetAlgebraicType(registrar)) + new("Unique2", Unique2RW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.SendMessageTimer.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.SendMessageTimer.verified.cs index de0599768a1..90065b14a30 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.SendMessageTimer.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#Timers.SendMessageTimer.verified.cs @@ -57,7 +57,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar { new("ScheduledId", ScheduledIdRW.GetAlgebraicType(registrar)), new("ScheduledAt", ScheduledAtRW.GetAlgebraicType(registrar)), - new("Text", TextRW.GetAlgebraicType(registrar)) + new("Text", TextRW.GetAlgebraicType(registrar)), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#BTreeMultiColumn.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#BTreeMultiColumn.verified.cs new file mode 100644 index 00000000000..6b55693551c --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#BTreeMultiColumn.verified.cs @@ -0,0 +1,117 @@ +//HintName: BTreeMultiColumn.cs +// +#nullable enable + +partial struct BTreeMultiColumn + : System.IEquatable, + SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) + { + X = BSATN.XRW.Read(reader); + Y = BSATN.YRW.Read(reader); + Z = BSATN.ZRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) + { + BSATN.XRW.Write(writer, X); + BSATN.YRW.Write(writer, Y); + BSATN.ZRW.Write(writer, Z); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => + $"BTreeMultiColumn {{ X = {SpacetimeDB.BSATN.StringUtil.GenericToString(X)}, Y = {SpacetimeDB.BSATN.StringUtil.GenericToString(Y)}, Z = {SpacetimeDB.BSATN.StringUtil.GenericToString(Z)} }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.U32 XRW = new(); + internal static readonly SpacetimeDB.BSATN.U32 YRW = new(); + internal static readonly SpacetimeDB.BSATN.U32 ZRW = new(); + + public BTreeMultiColumn Read(System.IO.BinaryReader reader) + { + var ___result = new BTreeMultiColumn(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, BTreeMultiColumn value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType( + _ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("X", XRW.GetAlgebraicType(registrar)), + new("Y", YRW.GetAlgebraicType(registrar)), + new("Z", ZRW.GetAlgebraicType(registrar)), + } + ) + ); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashX = X.GetHashCode(); + var ___hashY = Y.GetHashCode(); + var ___hashZ = Z.GetHashCode(); + return ___hashX ^ ___hashY ^ ___hashZ; + } + +#nullable enable + public bool Equals(BTreeMultiColumn that) + { + var ___eqX = this.X.Equals(that.X); + var ___eqY = this.Y.Equals(that.Y); + var ___eqZ = this.Z.Equals(that.Z); + return ___eqX && ___eqY && ___eqZ; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as BTreeMultiColumn?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(BTreeMultiColumn this_, BTreeMultiColumn that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(BTreeMultiColumn this_, BTreeMultiColumn that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // BTreeMultiColumn diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#BTreeViews.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#BTreeViews.verified.cs new file mode 100644 index 00000000000..c31ba82463d --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#BTreeViews.verified.cs @@ -0,0 +1,120 @@ +//HintName: BTreeViews.cs +// +#nullable enable + +partial struct BTreeViews : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) + { + Id = BSATN.IdRW.Read(reader); + X = BSATN.XRW.Read(reader); + Y = BSATN.YRW.Read(reader); + Faction = BSATN.FactionRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) + { + BSATN.IdRW.Write(writer, Id); + BSATN.XRW.Write(writer, X); + BSATN.YRW.Write(writer, Y); + BSATN.FactionRW.Write(writer, Faction); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => + $"BTreeViews {{ Id = {SpacetimeDB.BSATN.StringUtil.GenericToString(Id)}, X = {SpacetimeDB.BSATN.StringUtil.GenericToString(X)}, Y = {SpacetimeDB.BSATN.StringUtil.GenericToString(Y)}, Faction = {SpacetimeDB.BSATN.StringUtil.GenericToString(Faction)} }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.Identity.BSATN IdRW = new(); + internal static readonly SpacetimeDB.BSATN.U32 XRW = new(); + internal static readonly SpacetimeDB.BSATN.U32 YRW = new(); + internal static readonly SpacetimeDB.BSATN.String FactionRW = new(); + + public BTreeViews Read(System.IO.BinaryReader reader) + { + var ___result = new BTreeViews(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, BTreeViews value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("Id", IdRW.GetAlgebraicType(registrar)), + new("X", XRW.GetAlgebraicType(registrar)), + new("Y", YRW.GetAlgebraicType(registrar)), + new("Faction", FactionRW.GetAlgebraicType(registrar)), + } + )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashId = Id.GetHashCode(); + var ___hashX = X.GetHashCode(); + var ___hashY = Y.GetHashCode(); + var ___hashFaction = Faction == null ? 0 : Faction.GetHashCode(); + return ___hashId ^ ___hashX ^ ___hashY ^ ___hashFaction; + } + +#nullable enable + public bool Equals(BTreeViews that) + { + var ___eqId = this.Id.Equals(that.Id); + var ___eqX = this.X.Equals(that.X); + var ___eqY = this.Y.Equals(that.Y); + var ___eqFaction = + this.Faction == null ? that.Faction == null : this.Faction.Equals(that.Faction); + return ___eqId && ___eqX && ___eqY && ___eqFaction; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as BTreeViews?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(BTreeViews this_, BTreeViews that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(BTreeViews this_, BTreeViews that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // BTreeViews diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs new file mode 100644 index 00000000000..dac447a1ebc --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs @@ -0,0 +1,4439 @@ +//HintName: FFI.cs +// +#nullable enable +// .NET 8 generates a module-local LocalReadOnly which shadows the runtime shell. +#pragma warning disable CS0436 +#pragma warning disable STDB_UNSTABLE + +#if NET10_0_OR_GREATER +global using SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C; +#endif +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Internal = SpacetimeDB.Internal; +using TxContext = SpacetimeDB.Internal.TxContext; +#if NET10_0_OR_GREATER +[assembly: global::SpacetimeDB.ModuleDescriptorAttribute( + typeof(global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor) +)] + +#endif + +namespace SpacetimeDB +{ +#if !NET10_0_OR_GREATER + internal readonly struct BTreeMultiColumnCols + { + public readonly global::SpacetimeDB.Col X; + public readonly global::SpacetimeDB.Col Y; + public readonly global::SpacetimeDB.Col Z; + + internal BTreeMultiColumnCols(string tableName) + { + X = new global::SpacetimeDB.Col(tableName, "X"); + Y = new global::SpacetimeDB.Col(tableName, "Y"); + Z = new global::SpacetimeDB.Col(tableName, "Z"); + } + } + + internal readonly struct BTreeMultiColumnIxCols + { + public readonly global::SpacetimeDB.IxCol X; + public readonly global::SpacetimeDB.IxCol Y; + public readonly global::SpacetimeDB.IxCol Z; + + internal BTreeMultiColumnIxCols(string tableName) + { + X = new global::SpacetimeDB.IxCol(tableName, "X"); + Y = new global::SpacetimeDB.IxCol(tableName, "Y"); + Z = new global::SpacetimeDB.IxCol(tableName, "Z"); + } + } + + public readonly partial struct QueryBuilder + { + internal global::SpacetimeDB.Table< + global::BTreeMultiColumn, + BTreeMultiColumnCols, + BTreeMultiColumnIxCols + > BTreeMultiColumn() => + new( + "BTreeMultiColumn", + new BTreeMultiColumnCols("BTreeMultiColumn"), + new BTreeMultiColumnIxCols("BTreeMultiColumn") + ); + } + + internal readonly struct BTreeViewsCols + { + public readonly global::SpacetimeDB.Col Id; + public readonly global::SpacetimeDB.Col X; + public readonly global::SpacetimeDB.Col Y; + public readonly global::SpacetimeDB.Col Faction; + + internal BTreeViewsCols(string tableName) + { + Id = new global::SpacetimeDB.Col( + tableName, + "Id" + ); + X = new global::SpacetimeDB.Col(tableName, "X"); + Y = new global::SpacetimeDB.Col(tableName, "Y"); + Faction = new global::SpacetimeDB.Col(tableName, "Faction"); + } + } + + internal readonly struct BTreeViewsIxCols + { + public readonly global::SpacetimeDB.IxCol Id; + public readonly global::SpacetimeDB.IxCol X; + public readonly global::SpacetimeDB.IxCol Y; + public readonly global::SpacetimeDB.IxCol Faction; + + internal BTreeViewsIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol( + tableName, + "Id" + ); + X = new global::SpacetimeDB.IxCol(tableName, "X"); + Y = new global::SpacetimeDB.IxCol(tableName, "Y"); + Faction = new global::SpacetimeDB.IxCol( + tableName, + "Faction" + ); + } + } + + public readonly partial struct QueryBuilder + { + internal global::SpacetimeDB.Table< + global::BTreeViews, + BTreeViewsCols, + BTreeViewsIxCols + > BTreeViews() => + new("BTreeViews", new BTreeViewsCols("BTreeViews"), new BTreeViewsIxCols("BTreeViews")); + } + + public readonly struct MultiTable1Cols + { + public readonly global::SpacetimeDB.Col Name; + public readonly global::SpacetimeDB.Col Foo; + public readonly global::SpacetimeDB.Col Bar; + + internal MultiTable1Cols(string tableName) + { + Name = new global::SpacetimeDB.Col(tableName, "Name"); + Foo = new global::SpacetimeDB.Col(tableName, "Foo"); + Bar = new global::SpacetimeDB.Col(tableName, "Bar"); + } + } + + public readonly struct MultiTable1IxCols + { + public readonly global::SpacetimeDB.IxCol Name; + public readonly global::SpacetimeDB.IxCol Foo; + + internal MultiTable1IxCols(string tableName) + { + Name = new global::SpacetimeDB.IxCol(tableName, "Name"); + Foo = new global::SpacetimeDB.IxCol(tableName, "Foo"); + } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::MultiTableRow, + MultiTable1Cols, + MultiTable1IxCols + > MultiTable1() => + new( + "MultiTable1", + new MultiTable1Cols("MultiTable1"), + new MultiTable1IxCols("MultiTable1") + ); + } + + public readonly struct MultiTable2Cols + { + public readonly global::SpacetimeDB.Col Name; + public readonly global::SpacetimeDB.Col Foo; + public readonly global::SpacetimeDB.Col Bar; + + internal MultiTable2Cols(string tableName) + { + Name = new global::SpacetimeDB.Col(tableName, "Name"); + Foo = new global::SpacetimeDB.Col(tableName, "Foo"); + Bar = new global::SpacetimeDB.Col(tableName, "Bar"); + } + } + + public readonly struct MultiTable2IxCols + { + internal MultiTable2IxCols(string tableName) { } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::MultiTableRow, + MultiTable2Cols, + MultiTable2IxCols + > MultiTable2() => + new( + "MultiTable2", + new MultiTable2Cols("MultiTable2"), + new MultiTable2IxCols("MultiTable2") + ); + } + + public readonly struct PrivateTableCols + { + internal PrivateTableCols(string tableName) { } + } + + public readonly struct PrivateTableIxCols + { + internal PrivateTableIxCols(string tableName) { } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::PrivateTable, + PrivateTableCols, + PrivateTableIxCols + > PrivateTable() => + new( + "PrivateTable", + new PrivateTableCols("PrivateTable"), + new PrivateTableIxCols("PrivateTable") + ); + } + + public readonly struct PublicTableCols + { + public readonly global::SpacetimeDB.Col Id; + public readonly global::SpacetimeDB.Col ByteField; + public readonly global::SpacetimeDB.Col UshortField; + public readonly global::SpacetimeDB.Col UintField; + public readonly global::SpacetimeDB.Col UlongField; + public readonly global::SpacetimeDB.Col UInt128Field; + public readonly global::SpacetimeDB.Col U128Field; + public readonly global::SpacetimeDB.Col U256Field; + public readonly global::SpacetimeDB.Col SbyteField; + public readonly global::SpacetimeDB.Col ShortField; + public readonly global::SpacetimeDB.Col IntField; + public readonly global::SpacetimeDB.Col LongField; + public readonly global::SpacetimeDB.Col Int128Field; + public readonly global::SpacetimeDB.Col I128Field; + public readonly global::SpacetimeDB.Col I256Field; + public readonly global::SpacetimeDB.Col BoolField; + public readonly global::SpacetimeDB.Col FloatField; + public readonly global::SpacetimeDB.Col DoubleField; + public readonly global::SpacetimeDB.Col StringField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + SpacetimeDB.Identity + > IdentityField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + SpacetimeDB.ConnectionId + > ConnectionIdField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + CustomStruct + > CustomStructField; + public readonly global::SpacetimeDB.Col CustomClassField; + public readonly global::SpacetimeDB.Col CustomEnumField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + CustomTaggedEnum + > CustomTaggedEnumField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + System.Collections.Generic.List + > ListField; + public readonly global::SpacetimeDB.Col NullableValueField; + public readonly global::SpacetimeDB.Col NullableReferenceField; + + internal PublicTableCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "Id"); + ByteField = new global::SpacetimeDB.Col( + tableName, + "ByteField" + ); + UshortField = new global::SpacetimeDB.Col( + tableName, + "UshortField" + ); + UintField = new global::SpacetimeDB.Col( + tableName, + "UintField" + ); + UlongField = new global::SpacetimeDB.Col( + tableName, + "UlongField" + ); + UInt128Field = new global::SpacetimeDB.Col( + tableName, + "UInt128Field" + ); + U128Field = new global::SpacetimeDB.Col( + tableName, + "U128Field" + ); + U256Field = new global::SpacetimeDB.Col( + tableName, + "U256Field" + ); + SbyteField = new global::SpacetimeDB.Col( + tableName, + "SbyteField" + ); + ShortField = new global::SpacetimeDB.Col( + tableName, + "ShortField" + ); + IntField = new global::SpacetimeDB.Col(tableName, "IntField"); + LongField = new global::SpacetimeDB.Col( + tableName, + "LongField" + ); + Int128Field = new global::SpacetimeDB.Col( + tableName, + "Int128Field" + ); + I128Field = new global::SpacetimeDB.Col( + tableName, + "I128Field" + ); + I256Field = new global::SpacetimeDB.Col( + tableName, + "I256Field" + ); + BoolField = new global::SpacetimeDB.Col( + tableName, + "BoolField" + ); + FloatField = new global::SpacetimeDB.Col( + tableName, + "FloatField" + ); + DoubleField = new global::SpacetimeDB.Col( + tableName, + "DoubleField" + ); + StringField = new global::SpacetimeDB.Col( + tableName, + "StringField" + ); + IdentityField = new global::SpacetimeDB.Col( + tableName, + "IdentityField" + ); + ConnectionIdField = new global::SpacetimeDB.Col< + global::PublicTable, + SpacetimeDB.ConnectionId + >(tableName, "ConnectionIdField"); + CustomStructField = new global::SpacetimeDB.Col( + tableName, + "CustomStructField" + ); + CustomClassField = new global::SpacetimeDB.Col( + tableName, + "CustomClassField" + ); + CustomEnumField = new global::SpacetimeDB.Col( + tableName, + "CustomEnumField" + ); + CustomTaggedEnumField = new global::SpacetimeDB.Col< + global::PublicTable, + CustomTaggedEnum + >(tableName, "CustomTaggedEnumField"); + ListField = new global::SpacetimeDB.Col< + global::PublicTable, + System.Collections.Generic.List + >(tableName, "ListField"); + NullableValueField = new global::SpacetimeDB.Col( + tableName, + "NullableValueField" + ); + NullableReferenceField = new global::SpacetimeDB.Col( + tableName, + "NullableReferenceField" + ); + } + } + + public readonly struct PublicTableIxCols + { + public readonly global::SpacetimeDB.IxCol Id; + + internal PublicTableIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "Id"); + } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::PublicTable, + PublicTableCols, + PublicTableIxCols + > PublicTable() => + new( + "PublicTable", + new PublicTableCols("PublicTable"), + new PublicTableIxCols("PublicTable") + ); + } + + internal readonly struct RegressionMultipleUniqueIndexesHadSameNameCols + { + public readonly global::SpacetimeDB.Col< + global::RegressionMultipleUniqueIndexesHadSameName, + uint + > Unique1; + public readonly global::SpacetimeDB.Col< + global::RegressionMultipleUniqueIndexesHadSameName, + uint + > Unique2; + + internal RegressionMultipleUniqueIndexesHadSameNameCols(string tableName) + { + Unique1 = new global::SpacetimeDB.Col< + global::RegressionMultipleUniqueIndexesHadSameName, + uint + >(tableName, "Unique1"); + Unique2 = new global::SpacetimeDB.Col< + global::RegressionMultipleUniqueIndexesHadSameName, + uint + >(tableName, "Unique2"); + } + } + + internal readonly struct RegressionMultipleUniqueIndexesHadSameNameIxCols + { + internal RegressionMultipleUniqueIndexesHadSameNameIxCols(string tableName) { } + } + + public readonly partial struct QueryBuilder + { + internal global::SpacetimeDB.Table< + global::RegressionMultipleUniqueIndexesHadSameName, + RegressionMultipleUniqueIndexesHadSameNameCols, + RegressionMultipleUniqueIndexesHadSameNameIxCols + > RegressionMultipleUniqueIndexesHadSameName() => + new( + "RegressionMultipleUniqueIndexesHadSameName", + new RegressionMultipleUniqueIndexesHadSameNameCols( + "RegressionMultipleUniqueIndexesHadSameName" + ), + new RegressionMultipleUniqueIndexesHadSameNameIxCols( + "RegressionMultipleUniqueIndexesHadSameName" + ) + ); + } + + public readonly struct SendMessageTimerCols + { + public readonly global::SpacetimeDB.Col ScheduledId; + public readonly global::SpacetimeDB.Col< + global::Timers.SendMessageTimer, + SpacetimeDB.ScheduleAt + > ScheduledAt; + public readonly global::SpacetimeDB.Col Text; + + internal SendMessageTimerCols(string tableName) + { + ScheduledId = new global::SpacetimeDB.Col( + tableName, + "ScheduledId" + ); + ScheduledAt = new global::SpacetimeDB.Col< + global::Timers.SendMessageTimer, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduledAt"); + Text = new global::SpacetimeDB.Col( + tableName, + "Text" + ); + } + } + + public readonly struct SendMessageTimerIxCols + { + public readonly global::SpacetimeDB.IxCol< + global::Timers.SendMessageTimer, + ulong + > ScheduledId; + + internal SendMessageTimerIxCols(string tableName) + { + ScheduledId = new global::SpacetimeDB.IxCol( + tableName, + "ScheduledId" + ); + } + } + + public readonly partial struct QueryBuilder + { + public global::SpacetimeDB.Table< + global::Timers.SendMessageTimer, + SendMessageTimerCols, + SendMessageTimerIxCols + > SendMessageTimer() => + new( + "SendMessageTimer", + new SendMessageTimerCols("SendMessageTimer"), + new SendMessageTimerIxCols("SendMessageTimer") + ); + } +#endif + + public static class Handlers { } + +#if !NET10_0_OR_GREATER + public sealed record ReducerContext : DbContext, Internal.IReducerContext + { + public readonly Identity Sender; + public readonly ConnectionId? ConnectionId; + public readonly Random Rng; + public readonly Timestamp Timestamp; + public readonly AuthCtx SenderAuth; + + // **Note:** must be 0..=u32::MAX + internal int CounterUuid; + public Identity DatabaseIdentity => Internal.IReducerContext.GetDatabaseIdentity(); + + // We keep this property for compatibility with existing module code. + [global::System.Obsolete( + "ReducerContext.Identity is deprecated. Use DatabaseIdentity instead." + )] + public Identity Identity => DatabaseIdentity; + + internal ReducerContext( + Identity identity, + ConnectionId? connectionId, + Random random, + Timestamp time, + AuthCtx? senderAuth = null + ) + { + Sender = identity; + ConnectionId = connectionId; + Rng = random; + Timestamp = time; + SenderAuth = senderAuth ?? AuthCtx.BuildFromSystemTables(connectionId, identity); + CounterUuid = 0; + } + + /// + /// Create a new random `v4` using the built-in RNG. + /// + /// + /// This method fills the random bytes using the context RNG. + /// + /// + /// + /// var uuid = ctx.NewUuidV4(); + /// Log.Info(uuid); + /// + /// + public Uuid NewUuidV4() + { + var bytes = new byte[16]; + Rng.NextBytes(bytes); + return Uuid.FromRandomBytesV4(bytes); + } + + /// + /// Create a new sortable `v7` using the built-in RNG, monotonic counter, + /// and timestamp. + /// + /// + /// A newly generated `v7` that is monotonically ordered + /// and suitable for use as a primary key or for ordered storage. + /// + /// + /// Thrown if generation fails. + /// + /// + /// + /// [SpacetimeDB.Reducer] + /// public static Guid GenerateUuidV7(ReducerContext ctx) + /// { + /// Guid uuid = ctx.NewUuidV7(); + /// Log.Info(uuid); + /// } + /// + /// + public Uuid NewUuidV7() + { + var bytes = new byte[4]; + Rng.NextBytes(bytes); + return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); + } + } + + public sealed partial class ProcedureContext : global::SpacetimeDB.ProcedureContextBase + { + private readonly Local _db = new(); + + internal ProcedureContext( + Identity identity, + ConnectionId? connectionId, + Random random, + Timestamp time + ) + : base(identity, connectionId, random, time) { } + + protected override global::SpacetimeDB.LocalBase CreateLocal() => _db; + + protected override global::SpacetimeDB.ProcedureTxContextBase CreateTxContext( + Internal.TxContext inner + ) => _cached ??= new ProcedureTxContext(inner); + + private ProcedureTxContext? _cached; + + public Local Db => _db; + + public TResult WithTx(Func body) => + base.WithTx(tx => body((ProcedureTxContext)tx)); + + public TxOutcome TryWithTx( + Func> body + ) + where TError : Exception => base.TryWithTx(tx => body((ProcedureTxContext)tx)); + + /// + /// Create a new random `v4` using the built-in RNG. + /// + /// + /// This method fills the random bytes using the context RNG. + /// + /// + /// + /// var uuid = ctx.NewUuidV4(); + /// Log.Info(uuid); + /// + /// + public Uuid NewUuidV4() + { + var bytes = new byte[16]; + Rng.NextBytes(bytes); + return Uuid.FromRandomBytesV4(bytes); + } + + /// + /// Create a new sortable `v7` using the built-in RNG, monotonic counter, + /// and timestamp. + /// + /// + /// A newly generated `v7` that is monotonically ordered + /// and suitable for use as a primary key or for ordered storage. + /// + /// + /// Thrown if UUID generation fails. + /// + /// + /// + /// [SpacetimeDB.Procedure] + /// public static Guid GenerateUuidV7(ReducerContext ctx) + /// { + /// Guid uuid = ctx.NewUuidV7(); + /// Log.Info(uuid); + /// } + /// + /// + public Uuid NewUuidV7() + { + var bytes = new byte[4]; + Rng.NextBytes(bytes); + return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); + } + } + + public sealed partial class HandlerContext : global::SpacetimeDB.HandlerContextBase + { + private readonly Local _db = new(); + + internal HandlerContext(Random random, Timestamp time) + : base(random, time) { } + + protected override global::SpacetimeDB.LocalBase CreateLocal() => _db; + + protected override global::SpacetimeDB.HandlerTxContextBase CreateTxContext( + Internal.TxContext inner + ) => _cached ??= new HandlerTxContext(inner); + + private HandlerTxContext? _cached; + + [Experimental("STDB_UNSTABLE")] + public TResult WithTx(Func body) => + base.WithTx(tx => body((HandlerTxContext)tx)); + + [Experimental("STDB_UNSTABLE")] + public TxOutcome TryWithTx( + Func> body + ) + where TError : Exception => base.TryWithTx(tx => body((HandlerTxContext)tx)); + + public Uuid NewUuidV4() + { + var bytes = new byte[16]; + Rng.NextBytes(bytes); + return Uuid.FromRandomBytesV4(bytes); + } + + public Uuid NewUuidV7() + { + var bytes = new byte[4]; + Rng.NextBytes(bytes); + return Uuid.FromCounterV7(ref CounterUuid, Timestamp, bytes); + } + } + + public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase + { + internal ProcedureTxContext(Internal.TxContext inner) + : base(inner) { } + + public new Local Db => (Local)base.Db; + } + + [Experimental("STDB_UNSTABLE")] + public sealed class HandlerTxContext : global::SpacetimeDB.HandlerTxContextBase + { + internal HandlerTxContext(Internal.TxContext inner) + : base(inner) { } + + public new Local Db => (Local)base.Db; + } + + public sealed class Local : global::SpacetimeDB.LocalBase + { + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeMultiColumn BTreeMultiColumn => + new(); + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeViews BTreeViews => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable1 MultiTable1 => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable2 MultiTable2 => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PrivateTable PrivateTable => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PublicTable PublicTable => + new(); + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.SendMessageTimer SendMessageTimer => + new(); + } + + public sealed record ViewContext : DbContext, Internal.IViewContext + { + public Identity Sender { get; } + + public QueryBuilder From => default; + + internal ViewContext(Identity sender, Internal.LocalReadOnly db) + : base(db) + { + Sender = sender; + } + } + + public sealed record AnonymousViewContext + : DbContext, + Internal.IAnonymousViewContext + { + public QueryBuilder From => default; + + internal AnonymousViewContext(Internal.LocalReadOnly db) + : base(db) { } + } +#endif +} + +#if NET10_0_OR_GREATER +namespace SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +{ + public static partial class AssemblyDescriptor + { + public const string LifecycleReducers = "Timers.Init (Init)"; + public const int ReducerCount = 6; + public const int ProcedureCount = 0; + public const int HttpHandlerCount = 0; + public const int ViewCount = 2; + public const int AnonymousViewCount = 1; + + public static global::SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink error + ) => + global::ModuleRegistration.CallLocalReducer( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink result_sink + ) => + global::ModuleRegistration.CallLocalProcedure( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + global::SpacetimeDB.Timestamp timestamp, + global::SpacetimeDB.Internal.BytesSource request, + global::SpacetimeDB.Internal.BytesSource request_body, + global::SpacetimeDB.Internal.BytesSink response_sink, + global::SpacetimeDB.Internal.BytesSink response_body_sink + ) => + global::ModuleRegistration.CallLocalHttpHandler( + id, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => + global::ModuleRegistration.CallLocalView( + id, + sender_0, + sender_1, + sender_2, + sender_3, + args, + sink + ); + + public static global::SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + global::SpacetimeDB.Internal.BytesSource args, + global::SpacetimeDB.Internal.BytesSink sink + ) => global::ModuleRegistration.CallLocalAnonymousView(id, args, sink); + + public static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null + ) => global::ModuleRegistration.Register(builder, httpBuilder); + + public readonly struct Tables + { + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeMultiColumn BTreeMultiColumn => + new(); + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeViews BTreeViews => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable1 MultiTable1 => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable2 MultiTable2 => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PrivateTable PrivateTable => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PublicTable PublicTable => + new(); + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.SendMessageTimer SendMessageTimer => + new(); + } + + public readonly struct ReadOnlyTables + { + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeMultiColumnReadOnly BTreeMultiColumn => + new(); + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeViewsReadOnly BTreeViews => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable1ReadOnly MultiTable1 => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable2ReadOnly MultiTable2 => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PrivateTableReadOnly PrivateTable => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PublicTableReadOnly PublicTable => + new(); + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly RegressionMultipleUniqueIndexesHadSameName => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.SendMessageTimerReadOnly SendMessageTimer => + new(); + } + + public readonly partial struct Queries { } + } + + public static class LocalTableExtensions + { + extension(global::SpacetimeDB.Local db) + { + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeMultiColumn BTreeMultiColumn => + new(); + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeViews BTreeViews => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable1 MultiTable1 => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable2 MultiTable2 => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PrivateTable PrivateTable => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PublicTable PublicTable => + new(); + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.SendMessageTimer SendMessageTimer => + new(); + } + } + + public static class ReadOnlyTableExtensions + { + extension(global::SpacetimeDB.Internal.LocalReadOnly db) + { + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeMultiColumnReadOnly BTreeMultiColumn => + new(); + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeViewsReadOnly BTreeViews => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable1ReadOnly MultiTable1 => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable2ReadOnly MultiTable2 => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PrivateTableReadOnly PrivateTable => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PublicTableReadOnly PublicTable => + new(); + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly RegressionMultipleUniqueIndexesHadSameName => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.SendMessageTimerReadOnly SendMessageTimer => + new(); + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) { } + } + + internal readonly struct BTreeMultiColumnCols + { + public readonly global::SpacetimeDB.Col X; + public readonly global::SpacetimeDB.Col Y; + public readonly global::SpacetimeDB.Col Z; + + internal BTreeMultiColumnCols(global::SpacetimeDB.SqlTableName tableName) + { + X = new global::SpacetimeDB.Col(tableName, "X"); + Y = new global::SpacetimeDB.Col(tableName, "Y"); + Z = new global::SpacetimeDB.Col(tableName, "Z"); + } + } + + internal readonly struct BTreeMultiColumnIxCols + { + public readonly global::SpacetimeDB.IxCol X; + public readonly global::SpacetimeDB.IxCol Y; + public readonly global::SpacetimeDB.IxCol Z; + + internal BTreeMultiColumnIxCols(global::SpacetimeDB.SqlTableName tableName) + { + X = new global::SpacetimeDB.IxCol(tableName, "X"); + Y = new global::SpacetimeDB.IxCol(tableName, "Y"); + Z = new global::SpacetimeDB.IxCol(tableName, "Z"); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + internal global::SpacetimeDB.Table< + global::BTreeMultiColumn, + BTreeMultiColumnCols, + BTreeMultiColumnIxCols + > BTreeMultiColumn() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeMultiColumn" + ); + return new( + tableName, + new BTreeMultiColumnCols(tableName), + new BTreeMultiColumnIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + internal global::SpacetimeDB.Table< + global::BTreeMultiColumn, + BTreeMultiColumnCols, + BTreeMultiColumnIxCols + > BTreeMultiColumn() => new AssemblyDescriptor.Queries().BTreeMultiColumn(); + } + } + + internal readonly struct BTreeViewsCols + { + public readonly global::SpacetimeDB.Col Id; + public readonly global::SpacetimeDB.Col X; + public readonly global::SpacetimeDB.Col Y; + public readonly global::SpacetimeDB.Col Faction; + + internal BTreeViewsCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.Col( + tableName, + "Id" + ); + X = new global::SpacetimeDB.Col(tableName, "X"); + Y = new global::SpacetimeDB.Col(tableName, "Y"); + Faction = new global::SpacetimeDB.Col(tableName, "Faction"); + } + } + + internal readonly struct BTreeViewsIxCols + { + public readonly global::SpacetimeDB.IxCol Id; + public readonly global::SpacetimeDB.IxCol X; + public readonly global::SpacetimeDB.IxCol Y; + public readonly global::SpacetimeDB.IxCol Faction; + + internal BTreeViewsIxCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.IxCol( + tableName, + "Id" + ); + X = new global::SpacetimeDB.IxCol(tableName, "X"); + Y = new global::SpacetimeDB.IxCol(tableName, "Y"); + Faction = new global::SpacetimeDB.IxCol( + tableName, + "Faction" + ); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + internal global::SpacetimeDB.Table< + global::BTreeViews, + BTreeViewsCols, + BTreeViewsIxCols + > BTreeViews() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews" + ); + return new( + tableName, + new BTreeViewsCols(tableName), + new BTreeViewsIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + internal global::SpacetimeDB.Table< + global::BTreeViews, + BTreeViewsCols, + BTreeViewsIxCols + > BTreeViews() => new AssemblyDescriptor.Queries().BTreeViews(); + } + } + + public readonly struct MultiTable1Cols + { + public readonly global::SpacetimeDB.Col Name; + public readonly global::SpacetimeDB.Col Foo; + public readonly global::SpacetimeDB.Col Bar; + + internal MultiTable1Cols(global::SpacetimeDB.SqlTableName tableName) + { + Name = new global::SpacetimeDB.Col(tableName, "Name"); + Foo = new global::SpacetimeDB.Col(tableName, "Foo"); + Bar = new global::SpacetimeDB.Col(tableName, "Bar"); + } + } + + public readonly struct MultiTable1IxCols + { + public readonly global::SpacetimeDB.IxCol Name; + public readonly global::SpacetimeDB.IxCol Foo; + + internal MultiTable1IxCols(global::SpacetimeDB.SqlTableName tableName) + { + Name = new global::SpacetimeDB.IxCol(tableName, "Name"); + Foo = new global::SpacetimeDB.IxCol(tableName, "Foo"); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::MultiTableRow, + MultiTable1Cols, + MultiTable1IxCols + > MultiTable1() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1" + ); + return new( + tableName, + new MultiTable1Cols(tableName), + new MultiTable1IxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::MultiTableRow, + MultiTable1Cols, + MultiTable1IxCols + > MultiTable1() => new AssemblyDescriptor.Queries().MultiTable1(); + } + } + + public readonly struct MultiTable2Cols + { + public readonly global::SpacetimeDB.Col Name; + public readonly global::SpacetimeDB.Col Foo; + public readonly global::SpacetimeDB.Col Bar; + + internal MultiTable2Cols(global::SpacetimeDB.SqlTableName tableName) + { + Name = new global::SpacetimeDB.Col(tableName, "Name"); + Foo = new global::SpacetimeDB.Col(tableName, "Foo"); + Bar = new global::SpacetimeDB.Col(tableName, "Bar"); + } + } + + public readonly struct MultiTable2IxCols + { + internal MultiTable2IxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::MultiTableRow, + MultiTable2Cols, + MultiTable2IxCols + > MultiTable2() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable2" + ); + return new( + tableName, + new MultiTable2Cols(tableName), + new MultiTable2IxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::MultiTableRow, + MultiTable2Cols, + MultiTable2IxCols + > MultiTable2() => new AssemblyDescriptor.Queries().MultiTable2(); + } + } + + public readonly struct PrivateTableCols + { + internal PrivateTableCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public readonly struct PrivateTableIxCols + { + internal PrivateTableIxCols(global::SpacetimeDB.SqlTableName tableName) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::PrivateTable, + PrivateTableCols, + PrivateTableIxCols + > PrivateTable() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PrivateTable" + ); + return new( + tableName, + new PrivateTableCols(tableName), + new PrivateTableIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::PrivateTable, + PrivateTableCols, + PrivateTableIxCols + > PrivateTable() => new AssemblyDescriptor.Queries().PrivateTable(); + } + } + + public readonly struct PublicTableCols + { + public readonly global::SpacetimeDB.Col Id; + public readonly global::SpacetimeDB.Col ByteField; + public readonly global::SpacetimeDB.Col UshortField; + public readonly global::SpacetimeDB.Col UintField; + public readonly global::SpacetimeDB.Col UlongField; + public readonly global::SpacetimeDB.Col UInt128Field; + public readonly global::SpacetimeDB.Col U128Field; + public readonly global::SpacetimeDB.Col U256Field; + public readonly global::SpacetimeDB.Col SbyteField; + public readonly global::SpacetimeDB.Col ShortField; + public readonly global::SpacetimeDB.Col IntField; + public readonly global::SpacetimeDB.Col LongField; + public readonly global::SpacetimeDB.Col Int128Field; + public readonly global::SpacetimeDB.Col I128Field; + public readonly global::SpacetimeDB.Col I256Field; + public readonly global::SpacetimeDB.Col BoolField; + public readonly global::SpacetimeDB.Col FloatField; + public readonly global::SpacetimeDB.Col DoubleField; + public readonly global::SpacetimeDB.Col StringField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + SpacetimeDB.Identity + > IdentityField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + SpacetimeDB.ConnectionId + > ConnectionIdField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + CustomStruct + > CustomStructField; + public readonly global::SpacetimeDB.Col CustomClassField; + public readonly global::SpacetimeDB.Col CustomEnumField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + CustomTaggedEnum + > CustomTaggedEnumField; + public readonly global::SpacetimeDB.Col< + global::PublicTable, + System.Collections.Generic.List + > ListField; + public readonly global::SpacetimeDB.Col NullableValueField; + public readonly global::SpacetimeDB.Col NullableReferenceField; + + internal PublicTableCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "Id"); + ByteField = new global::SpacetimeDB.Col( + tableName, + "ByteField" + ); + UshortField = new global::SpacetimeDB.Col( + tableName, + "UshortField" + ); + UintField = new global::SpacetimeDB.Col( + tableName, + "UintField" + ); + UlongField = new global::SpacetimeDB.Col( + tableName, + "UlongField" + ); + UInt128Field = new global::SpacetimeDB.Col( + tableName, + "UInt128Field" + ); + U128Field = new global::SpacetimeDB.Col( + tableName, + "U128Field" + ); + U256Field = new global::SpacetimeDB.Col( + tableName, + "U256Field" + ); + SbyteField = new global::SpacetimeDB.Col( + tableName, + "SbyteField" + ); + ShortField = new global::SpacetimeDB.Col( + tableName, + "ShortField" + ); + IntField = new global::SpacetimeDB.Col(tableName, "IntField"); + LongField = new global::SpacetimeDB.Col( + tableName, + "LongField" + ); + Int128Field = new global::SpacetimeDB.Col( + tableName, + "Int128Field" + ); + I128Field = new global::SpacetimeDB.Col( + tableName, + "I128Field" + ); + I256Field = new global::SpacetimeDB.Col( + tableName, + "I256Field" + ); + BoolField = new global::SpacetimeDB.Col( + tableName, + "BoolField" + ); + FloatField = new global::SpacetimeDB.Col( + tableName, + "FloatField" + ); + DoubleField = new global::SpacetimeDB.Col( + tableName, + "DoubleField" + ); + StringField = new global::SpacetimeDB.Col( + tableName, + "StringField" + ); + IdentityField = new global::SpacetimeDB.Col( + tableName, + "IdentityField" + ); + ConnectionIdField = new global::SpacetimeDB.Col< + global::PublicTable, + SpacetimeDB.ConnectionId + >(tableName, "ConnectionIdField"); + CustomStructField = new global::SpacetimeDB.Col( + tableName, + "CustomStructField" + ); + CustomClassField = new global::SpacetimeDB.Col( + tableName, + "CustomClassField" + ); + CustomEnumField = new global::SpacetimeDB.Col( + tableName, + "CustomEnumField" + ); + CustomTaggedEnumField = new global::SpacetimeDB.Col< + global::PublicTable, + CustomTaggedEnum + >(tableName, "CustomTaggedEnumField"); + ListField = new global::SpacetimeDB.Col< + global::PublicTable, + System.Collections.Generic.List + >(tableName, "ListField"); + NullableValueField = new global::SpacetimeDB.Col( + tableName, + "NullableValueField" + ); + NullableReferenceField = new global::SpacetimeDB.Col( + tableName, + "NullableReferenceField" + ); + } + } + + public readonly struct PublicTableIxCols + { + public readonly global::SpacetimeDB.IxCol Id; + + internal PublicTableIxCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "Id"); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::PublicTable, + PublicTableCols, + PublicTableIxCols + > PublicTable() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PublicTable" + ); + return new( + tableName, + new PublicTableCols(tableName), + new PublicTableIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::PublicTable, + PublicTableCols, + PublicTableIxCols + > PublicTable() => new AssemblyDescriptor.Queries().PublicTable(); + } + } + + internal readonly struct RegressionMultipleUniqueIndexesHadSameNameCols + { + public readonly global::SpacetimeDB.Col< + global::RegressionMultipleUniqueIndexesHadSameName, + uint + > Unique1; + public readonly global::SpacetimeDB.Col< + global::RegressionMultipleUniqueIndexesHadSameName, + uint + > Unique2; + + internal RegressionMultipleUniqueIndexesHadSameNameCols( + global::SpacetimeDB.SqlTableName tableName + ) + { + Unique1 = new global::SpacetimeDB.Col< + global::RegressionMultipleUniqueIndexesHadSameName, + uint + >(tableName, "Unique1"); + Unique2 = new global::SpacetimeDB.Col< + global::RegressionMultipleUniqueIndexesHadSameName, + uint + >(tableName, "Unique2"); + } + } + + internal readonly struct RegressionMultipleUniqueIndexesHadSameNameIxCols + { + internal RegressionMultipleUniqueIndexesHadSameNameIxCols( + global::SpacetimeDB.SqlTableName tableName + ) { } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + internal global::SpacetimeDB.Table< + global::RegressionMultipleUniqueIndexesHadSameName, + RegressionMultipleUniqueIndexesHadSameNameCols, + RegressionMultipleUniqueIndexesHadSameNameIxCols + > RegressionMultipleUniqueIndexesHadSameName() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName" + ); + return new( + tableName, + new RegressionMultipleUniqueIndexesHadSameNameCols(tableName), + new RegressionMultipleUniqueIndexesHadSameNameIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + internal global::SpacetimeDB.Table< + global::RegressionMultipleUniqueIndexesHadSameName, + RegressionMultipleUniqueIndexesHadSameNameCols, + RegressionMultipleUniqueIndexesHadSameNameIxCols + > RegressionMultipleUniqueIndexesHadSameName() => + new AssemblyDescriptor.Queries().RegressionMultipleUniqueIndexesHadSameName(); + } + } + + public readonly struct SendMessageTimerCols + { + public readonly global::SpacetimeDB.Col ScheduledId; + public readonly global::SpacetimeDB.Col< + global::Timers.SendMessageTimer, + SpacetimeDB.ScheduleAt + > ScheduledAt; + public readonly global::SpacetimeDB.Col Text; + + internal SendMessageTimerCols(global::SpacetimeDB.SqlTableName tableName) + { + ScheduledId = new global::SpacetimeDB.Col( + tableName, + "ScheduledId" + ); + ScheduledAt = new global::SpacetimeDB.Col< + global::Timers.SendMessageTimer, + SpacetimeDB.ScheduleAt + >(tableName, "ScheduledAt"); + Text = new global::SpacetimeDB.Col( + tableName, + "Text" + ); + } + } + + public readonly struct SendMessageTimerIxCols + { + public readonly global::SpacetimeDB.IxCol< + global::Timers.SendMessageTimer, + ulong + > ScheduledId; + + internal SendMessageTimerIxCols(global::SpacetimeDB.SqlTableName tableName) + { + ScheduledId = new global::SpacetimeDB.IxCol( + tableName, + "ScheduledId" + ); + } + } + + public static partial class AssemblyDescriptor + { + public readonly partial struct Queries + { + public global::SpacetimeDB.Table< + global::Timers.SendMessageTimer, + SendMessageTimerCols, + SendMessageTimerIxCols + > SendMessageTimer() + { + var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "SendMessageTimer" + ); + return new( + tableName, + new SendMessageTimerCols(tableName), + new SendMessageTimerIxCols(tableName) + ); + } + } + } + + public static partial class QueryTableExtensions + { + extension(global::SpacetimeDB.QueryBuilder from) + { + public global::SpacetimeDB.Table< + global::Timers.SendMessageTimer, + SendMessageTimerCols, + SendMessageTimerIxCols + > SendMessageTimer() => new AssemblyDescriptor.Queries().SendMessageTimer(); + } + } +} +#endif + +namespace SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles +{ + internal readonly struct BTreeMultiColumn + : global::SpacetimeDB.Internal.ITableView + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeMultiColumn" + ); + + public static global::BTreeMultiColumn ReadGenFields( + System.IO.BinaryReader reader, + global::BTreeMultiColumn row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(BTreeMultiColumn), + ProductTypeRef: (uint) + new global::BTreeMultiColumn.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: + [ + new( + SourceName: "BTreeMultiColumn_X_Y_Z_idx_btree", + AccessorName: "Location", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0, 1, 2]) + ), + ], + Constraints: [], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + BTreeMultiColumn, + global::BTreeMultiColumn + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + BTreeMultiColumn, + global::BTreeMultiColumn + >.DoIter(); + + public global::BTreeMultiColumn Insert(global::BTreeMultiColumn row) => + global::SpacetimeDB.Internal.ITableView< + BTreeMultiColumn, + global::BTreeMultiColumn + >.DoInsert(row); + + public bool Delete(global::BTreeMultiColumn row) => + global::SpacetimeDB.Internal.ITableView< + BTreeMultiColumn, + global::BTreeMultiColumn + >.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView< + BTreeMultiColumn, + global::BTreeMultiColumn + >.DoClear(); + + internal sealed class LocationIndex() + : SpacetimeDB.Internal.IndexBase( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeMultiColumn_X_Y_Z_idx_btree" + ) + ) + { + public IEnumerable Filter(uint X) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public ulong Delete(uint X) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public IEnumerable Filter( + global::SpacetimeDB.Bound X + ) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public ulong Delete(global::SpacetimeDB.Bound X) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public IEnumerable Filter((uint X, uint Y) f) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public ulong Delete((uint X, uint Y) f) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public IEnumerable Filter( + (uint X, global::SpacetimeDB.Bound Y) f + ) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public ulong Delete((uint X, global::SpacetimeDB.Bound Y) f) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public IEnumerable Filter((uint X, uint Y, uint Z) f) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public ulong Delete((uint X, uint Y, uint Z) f) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public IEnumerable Filter( + (uint X, uint Y, global::SpacetimeDB.Bound Z) f + ) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public ulong Delete((uint X, uint Y, global::SpacetimeDB.Bound Z) f) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + } + + internal LocationIndex Location => new(); + } + + internal readonly struct BTreeViews + : global::SpacetimeDB.Internal.ITableView + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews" + ); + + public static global::BTreeViews ReadGenFields( + System.IO.BinaryReader reader, + global::BTreeViews row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(BTreeViews), + ProductTypeRef: (uint) + new global::BTreeViews.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [0], + Indexes: + [ + new( + SourceName: "BTreeViews_Id_idx_btree", + AccessorName: "Id", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + new( + SourceName: "BTreeViews_X_Y_idx_btree", + AccessorName: "Location", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1, 2]) + ), + new( + SourceName: "BTreeViews_Faction_idx_btree", + AccessorName: "Faction", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([3]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + BTreeViews, + global::BTreeViews + >.MakeUniqueConstraint(0), + ], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView.DoIter(); + + public global::BTreeViews Insert(global::BTreeViews row) => + global::SpacetimeDB.Internal.ITableView.DoInsert(row); + + public bool Delete(global::BTreeViews row) => + global::SpacetimeDB.Internal.ITableView.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView.DoClear(); + + internal sealed class IdUniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + BTreeViews, + global::BTreeViews, + SpacetimeDB.Identity, + SpacetimeDB.Identity.BSATN + > + { + internal IdUniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews_Id_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::BTreeViews? Find(SpacetimeDB.Identity key) => FindSingle(key); + + public global::BTreeViews Update(global::BTreeViews row) => DoUpdate(row); + } + + internal IdUniqueIndex Id => new(); + + internal sealed class LocationIndex() + : SpacetimeDB.Internal.IndexBase( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews_X_Y_idx_btree" + ) + ) + { + public IEnumerable Filter(uint X) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public ulong Delete(uint X) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public IEnumerable Filter(global::SpacetimeDB.Bound X) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public ulong Delete(global::SpacetimeDB.Bound X) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public IEnumerable Filter((uint X, uint Y) f) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public ulong Delete((uint X, uint Y) f) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public IEnumerable Filter( + (uint X, global::SpacetimeDB.Bound Y) f + ) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public ulong Delete((uint X, global::SpacetimeDB.Bound Y) f) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + } + + internal LocationIndex Location => new(); + + internal sealed class FactionIndex() + : SpacetimeDB.Internal.IndexBase( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews_Faction_idx_btree" + ) + ) + { + public IEnumerable Filter(string Faction) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + Faction + ) + ); + + public ulong Delete(string Faction) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + Faction + ) + ); + + public IEnumerable Filter( + global::SpacetimeDB.Bound Faction + ) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + Faction + ) + ); + + public ulong Delete(global::SpacetimeDB.Bound Faction) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + Faction + ) + ); + } + + internal FactionIndex Faction => new(); + } + + public readonly struct MultiTable1 + : global::SpacetimeDB.Internal.ITableView + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1" + ); + + public static global::MultiTableRow ReadGenFields( + System.IO.BinaryReader reader, + global::MultiTableRow row + ) + { + if (row.Foo == default) + { + row.Foo = global::MultiTableRow.BSATN.FooRW.Read(reader); + } + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(MultiTable1), + ProductTypeRef: (uint) + new global::MultiTableRow.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [1], + Indexes: + [ + new( + SourceName: "MultiTable1_Foo_idx_btree", + AccessorName: "Foo", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) + ), + new( + SourceName: "MultiTable1_Name_idx_btree", + AccessorName: "Name", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + MultiTable1, + global::MultiTableRow + >.MakeUniqueConstraint(1), + ], + Sequences: + [ + global::SpacetimeDB.Internal.ITableView< + MultiTable1, + global::MultiTableRow + >.MakeSequence(1), + ], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Public, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView.DoIter(); + + public global::MultiTableRow Insert(global::MultiTableRow row) => + global::SpacetimeDB.Internal.ITableView.DoInsert( + row + ); + + public bool Delete(global::MultiTableRow row) => + global::SpacetimeDB.Internal.ITableView.DoDelete( + row + ); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView.DoClear(); + + public sealed class FooUniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + MultiTable1, + global::MultiTableRow, + uint, + SpacetimeDB.BSATN.U32 + > + { + internal FooUniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1_Foo_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::MultiTableRow? Find(uint key) => FindSingle(key); + + public global::MultiTableRow Update(global::MultiTableRow row) => DoUpdate(row); + } + + public FooUniqueIndex Foo => new(); + + public sealed class NameIndex() + : SpacetimeDB.Internal.IndexBase( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1_Name_idx_btree" + ) + ) + { + public IEnumerable Filter(string Name) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + Name + ) + ); + + public ulong Delete(string Name) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + Name + ) + ); + + public IEnumerable Filter( + global::SpacetimeDB.Bound Name + ) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + Name + ) + ); + + public ulong Delete(global::SpacetimeDB.Bound Name) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + Name + ) + ); + } + + public NameIndex Name => new(); + } + + public readonly struct MultiTable2 + : global::SpacetimeDB.Internal.ITableView + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable2" + ); + + public static global::MultiTableRow ReadGenFields( + System.IO.BinaryReader reader, + global::MultiTableRow row + ) + { + if (row.Foo == default) + { + row.Foo = global::MultiTableRow.BSATN.FooRW.Read(reader); + } + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(MultiTable2), + ProductTypeRef: (uint) + new global::MultiTableRow.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: + [ + new( + SourceName: "MultiTable2_Bar_idx_btree", + AccessorName: "Bar", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([2]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + MultiTable2, + global::MultiTableRow + >.MakeUniqueConstraint(2), + ], + Sequences: + [ + global::SpacetimeDB.Internal.ITableView< + MultiTable2, + global::MultiTableRow + >.MakeSequence(1), + ], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView.DoIter(); + + public global::MultiTableRow Insert(global::MultiTableRow row) => + global::SpacetimeDB.Internal.ITableView.DoInsert( + row + ); + + public bool Delete(global::MultiTableRow row) => + global::SpacetimeDB.Internal.ITableView.DoDelete( + row + ); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView.DoClear(); + + public sealed class BarUniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + MultiTable2, + global::MultiTableRow, + uint, + SpacetimeDB.BSATN.U32 + > + { + internal BarUniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable2_Bar_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::MultiTableRow? Find(uint key) => FindSingle(key); + } + + public BarUniqueIndex Bar => new(); + } + + public readonly struct PrivateTable + : global::SpacetimeDB.Internal.ITableView + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PrivateTable" + ); + + public static global::PrivateTable ReadGenFields( + System.IO.BinaryReader reader, + global::PrivateTable row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(PrivateTable), + ProductTypeRef: (uint) + new global::PrivateTable.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: [], + Constraints: [], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: true + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView.DoIter(); + + public global::PrivateTable Insert(global::PrivateTable row) => + global::SpacetimeDB.Internal.ITableView.DoInsert( + row + ); + + public bool Delete(global::PrivateTable row) => + global::SpacetimeDB.Internal.ITableView.DoDelete( + row + ); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView.DoClear(); + } + + public readonly struct PublicTable + : global::SpacetimeDB.Internal.ITableView + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PublicTable" + ); + + public static global::PublicTable ReadGenFields( + System.IO.BinaryReader reader, + global::PublicTable row + ) + { + if (row.Id == default) + { + row.Id = global::PublicTable.BSATN.IdRW.Read(reader); + } + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(PublicTable), + ProductTypeRef: (uint) + new global::PublicTable.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [0], + Indexes: + [ + new( + SourceName: "PublicTable_Id_idx_btree", + AccessorName: "Id", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + PublicTable, + global::PublicTable + >.MakeUniqueConstraint(0), + ], + Sequences: + [ + global::SpacetimeDB.Internal.ITableView< + PublicTable, + global::PublicTable + >.MakeSequence(0), + ], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Public, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView.DoIter(); + + public global::PublicTable Insert(global::PublicTable row) => + global::SpacetimeDB.Internal.ITableView.DoInsert(row); + + public bool Delete(global::PublicTable row) => + global::SpacetimeDB.Internal.ITableView.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView.DoClear(); + + public sealed class IdUniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + PublicTable, + global::PublicTable, + int, + SpacetimeDB.BSATN.I32 + > + { + internal IdUniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PublicTable_Id_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::PublicTable? Find(int key) => FindSingle(key); + + public global::PublicTable Update(global::PublicTable row) => DoUpdate(row); + } + + public IdUniqueIndex Id => new(); + } + + internal readonly struct RegressionMultipleUniqueIndexesHadSameName + : global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + > + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName" + ); + + public static global::RegressionMultipleUniqueIndexesHadSameName ReadGenFields( + System.IO.BinaryReader reader, + global::RegressionMultipleUniqueIndexesHadSameName row + ) + { + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(RegressionMultipleUniqueIndexesHadSameName), + ProductTypeRef: (uint) + new global::RegressionMultipleUniqueIndexesHadSameName.BSATN() + .GetAlgebraicType(registrar) + .Ref_, + PrimaryKey: [], + Indexes: + [ + new( + SourceName: "RegressionMultipleUniqueIndexesHadSameName_Unique1_idx_btree", + AccessorName: "Unique1", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + new( + SourceName: "RegressionMultipleUniqueIndexesHadSameName_Unique2_idx_btree", + AccessorName: "Unique2", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + >.MakeUniqueConstraint(0), + global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + >.MakeUniqueConstraint(1), + ], + Sequences: [], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => null; + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + >.DoIter(); + + public global::RegressionMultipleUniqueIndexesHadSameName Insert( + global::RegressionMultipleUniqueIndexesHadSameName row + ) => + global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + >.DoInsert(row); + + public bool Delete(global::RegressionMultipleUniqueIndexesHadSameName row) => + global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + >.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + >.DoClear(); + + internal sealed class Unique1UniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName, + uint, + SpacetimeDB.BSATN.U32 + > + { + internal Unique1UniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName_Unique1_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::RegressionMultipleUniqueIndexesHadSameName? Find(uint key) => + FindSingle(key); + } + + internal Unique1UniqueIndex Unique1 => new(); + + internal sealed class Unique2UniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName, + uint, + SpacetimeDB.BSATN.U32 + > + { + internal Unique2UniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName_Unique2_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::RegressionMultipleUniqueIndexesHadSameName? Find(uint key) => + FindSingle(key); + } + + internal Unique2UniqueIndex Unique2 => new(); + } + + public readonly struct SendMessageTimer + : global::SpacetimeDB.Internal.ITableView + { + public static string LookupName => + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "SendMessageTimer" + ); + + public static global::Timers.SendMessageTimer ReadGenFields( + System.IO.BinaryReader reader, + global::Timers.SendMessageTimer row + ) + { + if (row.ScheduledId == default) + { + row.ScheduledId = global::Timers.SendMessageTimer.BSATN.ScheduledIdRW.Read(reader); + } + return row; + } + + public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(SendMessageTimer), + ProductTypeRef: (uint) + new global::Timers.SendMessageTimer.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [0], + Indexes: + [ + new( + SourceName: "SendMessageTimer_ScheduledId_idx_btree", + AccessorName: "ScheduledId", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.MakeUniqueConstraint(0), + ], + Sequences: + [ + global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.MakeSequence(0), + ], + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private, + DefaultValues: [], + IsEvent: false + ); + + public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => + global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.MakeSchedule("SendScheduledMessage", 1); + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.DoIter(); + + public global::Timers.SendMessageTimer Insert(global::Timers.SendMessageTimer row) => + global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.DoInsert(row); + + public bool Delete(global::Timers.SendMessageTimer row) => + global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.DoDelete(row); + + public ulong Clear() => + global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.DoClear(); + + public sealed class ScheduledIdUniqueIndex + : global::SpacetimeDB.Internal.UniqueIndex< + SendMessageTimer, + global::Timers.SendMessageTimer, + ulong, + SpacetimeDB.BSATN.U64 + > + { + internal ScheduledIdUniqueIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "SendMessageTimer_ScheduledId_idx_btree" + ) + ) { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::Timers.SendMessageTimer? Find(ulong key) => FindSingle(key); + + public global::Timers.SendMessageTimer Update(global::Timers.SendMessageTimer row) => + DoUpdate(row); + } + + public ScheduledIdUniqueIndex ScheduledId => new(); + } +} + +sealed class public_table_queryViewDispatcher : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "public_table_query", + Index: 0, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: global::SpacetimeDB.BSATN.AlgebraicType.MakeQueryBuilderProductType( + new PublicTable.BSATN().GetAlgebraicType(registrar) + ) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.PublicTableQuery((SpacetimeDB.ViewContext)ctx); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RawSql( + returnValue.ToSql() + ); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'public_table_query': " + e); + throw; + } + } +} + +sealed class public_table_viewViewDispatcher : global::SpacetimeDB.Internal.IView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "public_table_view", + Index: 1, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.ValueOption< + PublicTable, + PublicTable.BSATN + >().GetAlgebraicType(registrar) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) + { + try + { + var returnValue = Module.PublicTableByIdentity((SpacetimeDB.ViewContext)ctx); + var listSerializer = SpacetimeDB.BSATN.ValueOption< + PublicTable, + PublicTable.BSATN + >.GetListSerializer(); + var listValue = ModuleRegistration.ToListOrEmpty(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'public_table_view': " + e); + throw; + } + } +} + +sealed class find_public_table__by_identityViewDispatcher + : global::SpacetimeDB.Internal.IAnonymousView +{ + public SpacetimeDB.Internal.RawViewDefV10 MakeAnonymousViewDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new global::SpacetimeDB.Internal.RawViewDefV10( + SourceName: "find_public_table__by_identity", + Index: 0, + IsPublic: true, + IsAnonymous: true, + Params: [], + ReturnType: new SpacetimeDB.BSATN.ValueOption< + PublicTable, + PublicTable.BSATN + >().GetAlgebraicType(registrar) + ); + + public static byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IAnonymousViewContext ctx + ) + { + try + { + var returnValue = Module.FindPublicTableByIdentity( + (SpacetimeDB.AnonymousViewContext)ctx + ); + var listSerializer = SpacetimeDB.BSATN.ValueOption< + PublicTable, + PublicTable.BSATN + >.GetListSerializer(); + var listValue = ModuleRegistration.ToListOrEmpty(returnValue); + var header = new global::SpacetimeDB.Internal.ViewResultHeader.RowData(default); + var headerRW = new global::SpacetimeDB.Internal.ViewResultHeader.BSATN(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + headerRW.Write(writer, header); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } + catch (System.Exception e) + { + global::SpacetimeDB.Log.Error("Error in view 'find_public_table__by_identity': " + e); + throw; + } + } +} + +namespace SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles +{ + internal sealed class BTreeMultiColumnReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal BTreeMultiColumnReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeMultiColumn" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class LocationIndex + : global::SpacetimeDB.Internal.ReadOnlyIndexBase + { + internal LocationIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeMultiColumn_X_Y_Z_idx_btree" + ) + ) { } + + public IEnumerable Filter(uint X) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds( + X + ) + ); + + public IEnumerable Filter( + global::SpacetimeDB.Bound X + ) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds( + X + ) + ); + + public IEnumerable Filter((uint X, uint Y) f) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public IEnumerable Filter( + (uint X, global::SpacetimeDB.Bound Y) f + ) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public IEnumerable Filter((uint X, uint Y, uint Z) f) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public IEnumerable Filter( + (uint X, uint Y, global::SpacetimeDB.Bound Z) f + ) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + } + + internal LocationIndex Location => new(); + } + + internal sealed class BTreeViewsReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal BTreeViewsReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class IdIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeViewsReadOnly, + global::BTreeViews, + SpacetimeDB.Identity, + SpacetimeDB.Identity.BSATN + > + { + internal IdIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews_Id_idx_btree" + ) + ) { } + + public global::BTreeViews? Find(SpacetimeDB.Identity key) => FindSingle(key); + } + + public IdIndex Id => new(); + + public sealed class LocationIndex + : global::SpacetimeDB.Internal.ReadOnlyIndexBase + { + internal LocationIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews_X_Y_idx_btree" + ) + ) { } + + public IEnumerable Filter(uint X) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds( + X + ) + ); + + public IEnumerable Filter(global::SpacetimeDB.Bound X) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds( + X + ) + ); + + public IEnumerable Filter((uint X, uint Y) f) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public IEnumerable Filter( + (uint X, global::SpacetimeDB.Bound Y) f + ) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + } + + internal LocationIndex Location => new(); + + public sealed class FactionIndex + : global::SpacetimeDB.Internal.ReadOnlyIndexBase + { + internal FactionIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews_Faction_idx_btree" + ) + ) { } + + public IEnumerable Filter(string Faction) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds< + string, + SpacetimeDB.BSATN.String + >(Faction) + ); + + public IEnumerable Filter( + global::SpacetimeDB.Bound Faction + ) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds< + string, + SpacetimeDB.BSATN.String + >(Faction) + ); + } + + internal FactionIndex Faction => new(); + } + + public sealed class MultiTable1ReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal MultiTable1ReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class FooIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable1ReadOnly, + global::MultiTableRow, + uint, + SpacetimeDB.BSATN.U32 + > + { + internal FooIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1_Foo_idx_btree" + ) + ) { } + + public global::MultiTableRow? Find(uint key) => FindSingle(key); + } + + public FooIndex Foo => new(); + + public sealed class NameIndex + : global::SpacetimeDB.Internal.ReadOnlyIndexBase + { + internal NameIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1_Name_idx_btree" + ) + ) { } + + public IEnumerable Filter(string Name) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds< + string, + SpacetimeDB.BSATN.String + >(Name) + ); + + public IEnumerable Filter( + global::SpacetimeDB.Bound Name + ) => + DoFilter( + new global::SpacetimeDB.Internal.BTreeIndexBounds< + string, + SpacetimeDB.BSATN.String + >(Name) + ); + } + + public NameIndex Name => new(); + } + + public sealed class MultiTable2ReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal MultiTable2ReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable2" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class BarIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable2ReadOnly, + global::MultiTableRow, + uint, + SpacetimeDB.BSATN.U32 + > + { + internal BarIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable2_Bar_idx_btree" + ) + ) { } + + public global::MultiTableRow? Find(uint key) => FindSingle(key); + } + + public BarIndex Bar => new(); + } + + public sealed class PrivateTableReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal PrivateTableReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PrivateTable" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + } + + public sealed class PublicTableReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal PublicTableReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PublicTable" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class IdIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PublicTableReadOnly, + global::PublicTable, + int, + SpacetimeDB.BSATN.I32 + > + { + internal IdIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PublicTable_Id_idx_btree" + ) + ) { } + + public global::PublicTable? Find(int key) => FindSingle(key); + } + + public IdIndex Id => new(); + } + + internal sealed class RegressionMultipleUniqueIndexesHadSameNameReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal RegressionMultipleUniqueIndexesHadSameNameReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class Unique1Index + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly, + global::RegressionMultipleUniqueIndexesHadSameName, + uint, + SpacetimeDB.BSATN.U32 + > + { + internal Unique1Index() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName_Unique1_idx_btree" + ) + ) { } + + public global::RegressionMultipleUniqueIndexesHadSameName? Find(uint key) => + FindSingle(key); + } + + public Unique1Index Unique1 => new(); + + public sealed class Unique2Index + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly, + global::RegressionMultipleUniqueIndexesHadSameName, + uint, + SpacetimeDB.BSATN.U32 + > + { + internal Unique2Index() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName_Unique2_idx_btree" + ) + ) { } + + public global::RegressionMultipleUniqueIndexesHadSameName? Find(uint key) => + FindSingle(key); + } + + public Unique2Index Unique2 => new(); + } + + public sealed class SendMessageTimerReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView + { + internal SendMessageTimerReadOnly() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "SendMessageTimer" + ) + ) { } + + /// + /// Returns the number of rows in this table. + /// + /// This reads datastore metadata, so it runs in constant time. + /// It also takes into account modifications by the current transaction. + /// + public ulong Count => DoCount(); + + public sealed class ScheduledIdIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.SendMessageTimerReadOnly, + global::Timers.SendMessageTimer, + ulong, + SpacetimeDB.BSATN.U64 + > + { + internal ScheduledIdIndex() + : base( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "SendMessageTimer_ScheduledId_idx_btree" + ) + ) { } + + public global::Timers.SendMessageTimer? Find(ulong key) => FindSingle(key); + } + + public ScheduledIdIndex ScheduledId => new(); + } +} + +#if !NET10_0_OR_GREATER +namespace SpacetimeDB.Internal +{ + public sealed partial class LocalReadOnly + { + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeMultiColumnReadOnly BTreeMultiColumn => + new(); + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeViewsReadOnly BTreeViews => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable1ReadOnly MultiTable1 => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable2ReadOnly MultiTable2 => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PrivateTableReadOnly PrivateTable => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PublicTableReadOnly PublicTable => + new(); + internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly RegressionMultipleUniqueIndexesHadSameName => + new(); + public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.SendMessageTimerReadOnly SendMessageTimer => + new(); + } +} +#endif + +static class ModuleRegistration +{ + // Module host calls are single-threaded in Wasm today, so the generated + // entrypoints reuse buffers across calls to avoid per-invocation allocation. + private static byte[] reducerArgsBuffer = new byte[0x10_000]; + private static byte[] procedureArgsBuffer = new byte[0x10_000]; + private static byte[] httpRequestBuffer = new byte[0x10_000]; + private static byte[] httpRequestBodyBuffer = new byte[0x10_000]; + private static byte[] viewArgsBuffer = new byte[0x10_000]; + private static byte[] anonymousViewArgsBuffer = new byte[0x10_000]; + + sealed class Init : SpacetimeDB.Internal.IReducer + { + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(Init), + Params: [], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => SpacetimeDB.Internal.Lifecycle.Init; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + Timers.Init((SpacetimeDB.ReducerContext)ctx); + } + } + + sealed class InsertData : SpacetimeDB.Internal.IReducer + { + private static readonly PublicTable.BSATN dataRW = new(); + + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(InsertData), + Params: [new("data", dataRW.GetAlgebraicType(registrar))], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => null; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + Reducers.InsertData((SpacetimeDB.ReducerContext)ctx, dataRW.Read(reader)); + } + } + + sealed class InsertData2 : SpacetimeDB.Internal.IReducer + { + private static readonly PublicTable.BSATN dataRW = new(); + + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(InsertData2), + Params: [new("data", dataRW.GetAlgebraicType(registrar))], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => null; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + Test.NestingNamespaces.AndClasses.InsertData2( + (SpacetimeDB.ReducerContext)ctx, + dataRW.Read(reader) + ); + } + } + + sealed class InsertMultiData : SpacetimeDB.Internal.IReducer + { + private static readonly MultiTableRow.BSATN dataRW = new(); + + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(InsertMultiData), + Params: [new("data", dataRW.GetAlgebraicType(registrar))], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => null; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + MultiTableRow.InsertMultiData((SpacetimeDB.ReducerContext)ctx, dataRW.Read(reader)); + } + } + + sealed class ScheduleImmediate : SpacetimeDB.Internal.IReducer + { + private static readonly PublicTable.BSATN dataRW = new(); + + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(ScheduleImmediate), + Params: [new("data", dataRW.GetAlgebraicType(registrar))], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => null; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + Reducers.ScheduleImmediate((SpacetimeDB.ReducerContext)ctx, dataRW.Read(reader)); + } + } + + sealed class SendScheduledMessage : SpacetimeDB.Internal.IReducer + { + private static readonly Timers.SendMessageTimer.BSATN argRW = new(); + + public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + new( + SourceName: nameof(SendScheduledMessage), + Params: [new("arg", argRW.GetAlgebraicType(registrar))], + Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable, + OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit, + ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default) + ); + + public SpacetimeDB.Internal.Lifecycle? Lifecycle => null; + + public static void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) + { + Timers.SendScheduledMessage((SpacetimeDB.ReducerContext)ctx, argRW.Read(reader)); + } + } + + public static List ToListOrEmpty(T? value) + where T : struct => value is null ? new List() : new List { value.Value }; + + public static List ToListOrEmpty(T? value) + where T : class => value is null ? new List() : new List { value }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + // In AOT mode we're building a library. + // Main method won't be called automatically, so we need to export it as a preinit function. + [UnmanagedCallersOnly(EntryPoint = "__preinit__10_init_csharp")] +#else + // Prevent trimming of FFI exports that are invoked from C and not visible to C# trimmer. + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, typeof(ModuleRegistration))] +#endif + public static void Main() => Initialize(); + + internal static void Initialize() + { +#if !NET10_0_OR_GREATER + SpacetimeDB.Internal.Module.SetReducerContextConstructor( + (identity, connectionId, random, time) => + new SpacetimeDB.ReducerContext(identity, connectionId, random, time) + ); + SpacetimeDB.Internal.Module.SetViewContextConstructor( + identity => new SpacetimeDB.ViewContext( + identity, + new SpacetimeDB.Internal.LocalReadOnly() + ) + ); + SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor(() => + new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly()) + ); + SpacetimeDB.Internal.Module.SetProcedureContextConstructor( + (identity, connectionId, random, time) => + new SpacetimeDB.ProcedureContext(identity, connectionId, random, time) + ); + SpacetimeDB.Internal.Module.SetHandlerContextConstructor( + (random, time) => new SpacetimeDB.HandlerContext(random, time) + ); +#endif + +#if NET10_0_OR_GREATER + global::SpacetimeDB.Internal.Module.InstallNamespaces( + new global::SpacetimeDB.Internal.NamespaceRegistry( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + new global::System.Collections.Generic.KeyValuePair[] { } + ) + ); + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Register( + global::SpacetimeDB.Internal.Module.RootBuilder + ); +#else + Register(global::SpacetimeDB.Internal.Module.RootBuilder); +#endif + } + + internal static void Register( + global::SpacetimeDB.Internal.ModuleBuilder builder, + global::SpacetimeDB.Internal.ModuleBuilder? httpBuilder = null + ) + { + // HTTP routes retain the root routing API even for mounted modules. + httpBuilder ??= builder; + + var __memoryStream = new MemoryStream(); + var __writer = new BinaryWriter(__memoryStream); + + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + builder.RegisterReducer(); + + // IMPORTANT: The order in which we register views matters. + // It must correspond to the order in which we call `GenerateDispatcherClass`. + // See the comment on `GenerateDispatcherClass` for more explanation. + builder.RegisterView(); + builder.RegisterView(); + builder.RegisterAnonymousView(); + + builder.RegisterTable< + global::BTreeMultiColumn, + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeMultiColumn + >(); + builder.RegisterTable< + global::BTreeViews, + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeViews + >(); + builder.RegisterTable< + global::MultiTableRow, + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable1 + >(); + builder.RegisterTable< + global::MultiTableRow, + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable2 + >(); + builder.RegisterTable< + global::PrivateTable, + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PrivateTable + >(); + builder.RegisterTable< + global::PublicTable, + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PublicTable + >(); + builder.RegisterTable< + global::RegressionMultipleUniqueIndexesHadSameName, + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.RegressionMultipleUniqueIndexesHadSameName + >(); + builder.RegisterTable< + global::Timers.SendMessageTimer, + global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.SendMessageTimer + >(); + + builder.RegisterClientVisibilityFilter(global::Module.ALL_PUBLIC_TABLES); + } + + // Export entrypoints live in generated module code so all build modes can + // dispatch directly to concrete generated functions. +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__describe_module__")] +#endif + public static void __describe_module__(SpacetimeDB.Internal.BytesSink d) => + SpacetimeDB.Internal.Module.__describe_module__(d); + + private static SpacetimeDB.Internal.Errno __call_reducer_0( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + Init.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_reducer_1( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + InsertData.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_reducer_2( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + InsertData2.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_reducer_3( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + InsertMultiData.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_reducer_4( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + ScheduleImmediate.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_reducer_5( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateReducerContext( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref reducerArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + SendScheduledMessage.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.EnsureNoUnreadBytes(stream, "reducer arguments"); + return SpacetimeDB.Internal.Errno.OK; + } + catch (System.Exception e) + { + return SpacetimeDB.Internal.Module.WriteReducerError(error, e); + } + } + + private static SpacetimeDB.Internal.Errno __call_view_0( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = public_table_queryViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_1( + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateViewContext( + sender_0, + sender_1, + sender_2, + sender_3 + ); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes(args, ref viewArgsBuffer); + using var reader = new System.IO.BinaryReader(stream); + var bytes = public_table_viewViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + + private static SpacetimeDB.Internal.Errno __call_view_anon_0( + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { + try + { + var ctx = SpacetimeDB.Internal.Module.CreateAnonymousViewContext(); + using var stream = SpacetimeDB.Internal.Module.ConsumeBytes( + args, + ref anonymousViewArgsBuffer + ); + using var reader = new System.IO.BinaryReader(stream); + var bytes = find_public_table__by_identityViewDispatcher.Invoke(reader, ctx); + SpacetimeDB.Internal.Module.WriteBytes(sink, bytes); + return (SpacetimeDB.Internal.Errno)2; + } + catch (System.Exception e) + { + SpacetimeDB.Log.Error($"Error while invoking anonymous view: {e}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + } + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_reducer__")] +#endif + public static SpacetimeDB.Internal.Errno __call_reducer__( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ReducerCount + ) + return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalReducer( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ReducerCount; + return SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ); +#else + return CallLocalReducer( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalReducer( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) => + id switch + { + 0 => __call_reducer_0( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 1 => __call_reducer_1( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 2 => __call_reducer_2( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 3 => __call_reducer_3( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 4 => __call_reducer_4( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + 5 => __call_reducer_5( + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ), + _ => SpacetimeDB.Internal.Module.WriteReducerError( + error, + new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown reducer id") + ), + }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_procedure__")] +#endif + public static SpacetimeDB.Internal.Errno __call_procedure__( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink result_sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ProcedureCount + ) + return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalProcedure( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ProcedureCount; + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); +#else + return CallLocalProcedure( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalProcedure( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink result_sink + ) => + id switch + { + _ => throw new System.ArgumentOutOfRangeException( + nameof(id), + id, + "Unknown procedure id" + ), + }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_http_handler__")] +#endif + public static SpacetimeDB.Internal.Errno __call_http_handler__( + int id, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource request, + SpacetimeDB.Internal.BytesSource request_body, + SpacetimeDB.Internal.BytesSink response_sink, + SpacetimeDB.Internal.BytesSink response_body_sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .HttpHandlerCount + ) + return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalHttpHandler( + localId, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .HttpHandlerCount; + throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); +#else + return CallLocalHttpHandler( + id, + timestamp, + request, + request_body, + response_sink, + response_body_sink + ); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalHttpHandler( + int id, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource request, + SpacetimeDB.Internal.BytesSource request_body, + SpacetimeDB.Internal.BytesSink response_sink, + SpacetimeDB.Internal.BytesSink response_body_sink + ) => + id switch + { + _ => throw new System.ArgumentOutOfRangeException( + nameof(id), + id, + "Unknown HTTP handler id" + ), + }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_view__")] +#endif + public static SpacetimeDB.Internal.Errno __call_view__( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return UnknownViewId(id); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ViewCount + ) + return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalView( + localId, + sender_0, + sender_1, + sender_2, + sender_3, + args, + sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .ViewCount; + return UnknownViewId(id); +#else + return CallLocalView(id, sender_0, sender_1, sender_2, sender_3, args, sink); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalView( + int id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) => + id switch + { + 0 => __call_view_0(sender_0, sender_1, sender_2, sender_3, args, sink), + 1 => __call_view_1(sender_0, sender_1, sender_2, sender_3, args, sink), + _ => UnknownViewId(id), + }; + +#if EXPERIMENTAL_WASM_AOT || NET10_0_OR_GREATER + [UnmanagedCallersOnly(EntryPoint = "__call_view_anon__")] +#endif + public static SpacetimeDB.Internal.Errno __call_view_anon__( + int id, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) + { +#if NET10_0_OR_GREATER + if (id < 0) + { + return UnknownAnonymousViewId(id); + } + var localId = id; + if ( + (uint)localId + < (uint) + global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .AnonymousViewCount + ) + return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalAnonymousView( + localId, + args, + sink + ); + localId -= global::SpacetimeDB + .Generated + .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .AssemblyDescriptor + .AnonymousViewCount; + return UnknownAnonymousViewId(id); +#else + return CallLocalAnonymousView(id, args, sink); +#endif + } + + internal static SpacetimeDB.Internal.Errno CallLocalAnonymousView( + int id, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) => + id switch + { + 0 => __call_view_anon_0(args, sink), + _ => UnknownAnonymousViewId(id), + }; + + private static SpacetimeDB.Internal.Errno UnknownViewId(int id) + { + SpacetimeDB.Log.Error($"Unknown view id: {id}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } + + private static SpacetimeDB.Internal.Errno UnknownAnonymousViewId(int id) + { + SpacetimeDB.Log.Error($"Unknown anonymous view id: {id}"); + return SpacetimeDB.Internal.Errno.HOST_CALL_FAILURE; + } +} + +#pragma warning restore STDB_UNSTABLE +#pragma warning restore CS0436 diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.InsertMultiData.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.InsertMultiData.verified.cs new file mode 100644 index 00000000000..d063fd6f7b2 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.InsertMultiData.verified.cs @@ -0,0 +1,21 @@ +//HintName: MultiTableRow.InsertMultiData.cs +// +#nullable enable + +partial struct MultiTableRow +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateInsertMultiData(MultiTableRow data) + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new MultiTableRow.BSATN().Write(writer, data); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(InsertMultiData) + ), + stream + ); + } +} // MultiTableRow diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.verified.cs new file mode 100644 index 00000000000..d5786199b4b --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.verified.cs @@ -0,0 +1,115 @@ +//HintName: MultiTableRow.cs +// +#nullable enable + +partial struct MultiTableRow + : System.IEquatable, + SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) + { + Name = BSATN.NameRW.Read(reader); + Foo = BSATN.FooRW.Read(reader); + Bar = BSATN.BarRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) + { + BSATN.NameRW.Write(writer, Name); + BSATN.FooRW.Write(writer, Foo); + BSATN.BarRW.Write(writer, Bar); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => + $"MultiTableRow {{ Name = {SpacetimeDB.BSATN.StringUtil.GenericToString(Name)}, Foo = {SpacetimeDB.BSATN.StringUtil.GenericToString(Foo)}, Bar = {SpacetimeDB.BSATN.StringUtil.GenericToString(Bar)} }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.String NameRW = new(); + internal static readonly SpacetimeDB.BSATN.U32 FooRW = new(); + internal static readonly SpacetimeDB.BSATN.U32 BarRW = new(); + + public MultiTableRow Read(System.IO.BinaryReader reader) + { + var ___result = new MultiTableRow(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, MultiTableRow value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("Name", NameRW.GetAlgebraicType(registrar)), + new("Foo", FooRW.GetAlgebraicType(registrar)), + new("Bar", BarRW.GetAlgebraicType(registrar)), + } + )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashName = Name == null ? 0 : Name.GetHashCode(); + var ___hashFoo = Foo.GetHashCode(); + var ___hashBar = Bar.GetHashCode(); + return ___hashName ^ ___hashFoo ^ ___hashBar; + } + +#nullable enable + public bool Equals(MultiTableRow that) + { + var ___eqName = this.Name == null ? that.Name == null : this.Name.Equals(that.Name); + var ___eqFoo = this.Foo.Equals(that.Foo); + var ___eqBar = this.Bar.Equals(that.Bar); + return ___eqName && ___eqFoo && ___eqBar; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as MultiTableRow?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(MultiTableRow this_, MultiTableRow that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(MultiTableRow this_, MultiTableRow that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // MultiTableRow diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#PrivateTable.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#PrivateTable.verified.cs new file mode 100644 index 00000000000..7904294b21b --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#PrivateTable.verified.cs @@ -0,0 +1,92 @@ +//HintName: PrivateTable.cs +// +#nullable enable + +partial class PrivateTable : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) { } + + public void WriteFields(System.IO.BinaryWriter writer) { } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => $"PrivateTable {{ }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + public PrivateTable Read(System.IO.BinaryReader reader) + { + var ___result = new PrivateTable(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, PrivateTable value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] { } + )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + return 0; + } + +#nullable enable + public bool Equals(PrivateTable? that) + { + if (((object?)that) == null) + { + return false; + } + + return true; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as PrivateTable; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(PrivateTable? this_, PrivateTable? that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(PrivateTable? this_, PrivateTable? that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // PrivateTable diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#PublicTable.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#PublicTable.verified.cs new file mode 100644 index 00000000000..66eb1f4dfe6 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#PublicTable.verified.cs @@ -0,0 +1,380 @@ +//HintName: PublicTable.cs +// +#nullable enable + +partial struct PublicTable : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) + { + Id = BSATN.IdRW.Read(reader); + ByteField = BSATN.ByteFieldRW.Read(reader); + UshortField = BSATN.UshortFieldRW.Read(reader); + UintField = BSATN.UintFieldRW.Read(reader); + UlongField = BSATN.UlongFieldRW.Read(reader); + UInt128Field = BSATN.UInt128FieldRW.Read(reader); + U128Field = BSATN.U128FieldRW.Read(reader); + U256Field = BSATN.U256FieldRW.Read(reader); + SbyteField = BSATN.SbyteFieldRW.Read(reader); + ShortField = BSATN.ShortFieldRW.Read(reader); + IntField = BSATN.IntFieldRW.Read(reader); + LongField = BSATN.LongFieldRW.Read(reader); + Int128Field = BSATN.Int128FieldRW.Read(reader); + I128Field = BSATN.I128FieldRW.Read(reader); + I256Field = BSATN.I256FieldRW.Read(reader); + BoolField = BSATN.BoolFieldRW.Read(reader); + FloatField = BSATN.FloatFieldRW.Read(reader); + DoubleField = BSATN.DoubleFieldRW.Read(reader); + StringField = BSATN.StringFieldRW.Read(reader); + IdentityField = BSATN.IdentityFieldRW.Read(reader); + ConnectionIdField = BSATN.ConnectionIdFieldRW.Read(reader); + CustomStructField = BSATN.CustomStructFieldRW.Read(reader); + CustomClassField = BSATN.CustomClassFieldRW.Read(reader); + CustomEnumField = BSATN.CustomEnumFieldRW.Read(reader); + CustomTaggedEnumField = BSATN.CustomTaggedEnumFieldRW.Read(reader); + ListField = BSATN.ListFieldRW.Read(reader); + NullableValueField = BSATN.NullableValueFieldRW.Read(reader); + NullableReferenceField = BSATN.NullableReferenceFieldRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) + { + BSATN.IdRW.Write(writer, Id); + BSATN.ByteFieldRW.Write(writer, ByteField); + BSATN.UshortFieldRW.Write(writer, UshortField); + BSATN.UintFieldRW.Write(writer, UintField); + BSATN.UlongFieldRW.Write(writer, UlongField); + BSATN.UInt128FieldRW.Write(writer, UInt128Field); + BSATN.U128FieldRW.Write(writer, U128Field); + BSATN.U256FieldRW.Write(writer, U256Field); + BSATN.SbyteFieldRW.Write(writer, SbyteField); + BSATN.ShortFieldRW.Write(writer, ShortField); + BSATN.IntFieldRW.Write(writer, IntField); + BSATN.LongFieldRW.Write(writer, LongField); + BSATN.Int128FieldRW.Write(writer, Int128Field); + BSATN.I128FieldRW.Write(writer, I128Field); + BSATN.I256FieldRW.Write(writer, I256Field); + BSATN.BoolFieldRW.Write(writer, BoolField); + BSATN.FloatFieldRW.Write(writer, FloatField); + BSATN.DoubleFieldRW.Write(writer, DoubleField); + BSATN.StringFieldRW.Write(writer, StringField); + BSATN.IdentityFieldRW.Write(writer, IdentityField); + BSATN.ConnectionIdFieldRW.Write(writer, ConnectionIdField); + BSATN.CustomStructFieldRW.Write(writer, CustomStructField); + BSATN.CustomClassFieldRW.Write(writer, CustomClassField); + BSATN.CustomEnumFieldRW.Write(writer, CustomEnumField); + BSATN.CustomTaggedEnumFieldRW.Write(writer, CustomTaggedEnumField); + BSATN.ListFieldRW.Write(writer, ListField); + BSATN.NullableValueFieldRW.Write(writer, NullableValueField); + BSATN.NullableReferenceFieldRW.Write(writer, NullableReferenceField); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => + $"PublicTable {{ Id = {SpacetimeDB.BSATN.StringUtil.GenericToString(Id)}, ByteField = {SpacetimeDB.BSATN.StringUtil.GenericToString(ByteField)}, UshortField = {SpacetimeDB.BSATN.StringUtil.GenericToString(UshortField)}, UintField = {SpacetimeDB.BSATN.StringUtil.GenericToString(UintField)}, UlongField = {SpacetimeDB.BSATN.StringUtil.GenericToString(UlongField)}, UInt128Field = {SpacetimeDB.BSATN.StringUtil.GenericToString(UInt128Field)}, U128Field = {SpacetimeDB.BSATN.StringUtil.GenericToString(U128Field)}, U256Field = {SpacetimeDB.BSATN.StringUtil.GenericToString(U256Field)}, SbyteField = {SpacetimeDB.BSATN.StringUtil.GenericToString(SbyteField)}, ShortField = {SpacetimeDB.BSATN.StringUtil.GenericToString(ShortField)}, IntField = {SpacetimeDB.BSATN.StringUtil.GenericToString(IntField)}, LongField = {SpacetimeDB.BSATN.StringUtil.GenericToString(LongField)}, Int128Field = {SpacetimeDB.BSATN.StringUtil.GenericToString(Int128Field)}, I128Field = {SpacetimeDB.BSATN.StringUtil.GenericToString(I128Field)}, I256Field = {SpacetimeDB.BSATN.StringUtil.GenericToString(I256Field)}, BoolField = {SpacetimeDB.BSATN.StringUtil.GenericToString(BoolField)}, FloatField = {SpacetimeDB.BSATN.StringUtil.GenericToString(FloatField)}, DoubleField = {SpacetimeDB.BSATN.StringUtil.GenericToString(DoubleField)}, StringField = {SpacetimeDB.BSATN.StringUtil.GenericToString(StringField)}, IdentityField = {SpacetimeDB.BSATN.StringUtil.GenericToString(IdentityField)}, ConnectionIdField = {SpacetimeDB.BSATN.StringUtil.GenericToString(ConnectionIdField)}, CustomStructField = {SpacetimeDB.BSATN.StringUtil.GenericToString(CustomStructField)}, CustomClassField = {SpacetimeDB.BSATN.StringUtil.GenericToString(CustomClassField)}, CustomEnumField = {SpacetimeDB.BSATN.StringUtil.GenericToString(CustomEnumField)}, CustomTaggedEnumField = {SpacetimeDB.BSATN.StringUtil.GenericToString(CustomTaggedEnumField)}, ListField = {SpacetimeDB.BSATN.StringUtil.GenericToString(ListField)}, NullableValueField = {SpacetimeDB.BSATN.StringUtil.GenericToString(NullableValueField)}, NullableReferenceField = {SpacetimeDB.BSATN.StringUtil.GenericToString(NullableReferenceField)} }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.I32 IdRW = new(); + internal static readonly SpacetimeDB.BSATN.U8 ByteFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.U16 UshortFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.U32 UintFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.U64 UlongFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.U128 UInt128FieldRW = new(); + internal static readonly SpacetimeDB.BSATN.U128Stdb U128FieldRW = new(); + internal static readonly SpacetimeDB.BSATN.U256 U256FieldRW = new(); + internal static readonly SpacetimeDB.BSATN.I8 SbyteFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.I16 ShortFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.I32 IntFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.I64 LongFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.I128 Int128FieldRW = new(); + internal static readonly SpacetimeDB.BSATN.I128Stdb I128FieldRW = new(); + internal static readonly SpacetimeDB.BSATN.I256 I256FieldRW = new(); + internal static readonly SpacetimeDB.BSATN.Bool BoolFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.F32 FloatFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.F64 DoubleFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.String StringFieldRW = new(); + internal static readonly SpacetimeDB.Identity.BSATN IdentityFieldRW = new(); + internal static readonly SpacetimeDB.ConnectionId.BSATN ConnectionIdFieldRW = new(); + internal static readonly CustomStruct.BSATN CustomStructFieldRW = new(); + internal static readonly CustomClass.BSATN CustomClassFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.Enum CustomEnumFieldRW = new(); + internal static readonly CustomTaggedEnum.BSATN CustomTaggedEnumFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.List ListFieldRW = + new(); + internal static readonly SpacetimeDB.BSATN.ValueOption< + int, + SpacetimeDB.BSATN.I32 + > NullableValueFieldRW = new(); + internal static readonly SpacetimeDB.BSATN.RefOption< + string, + SpacetimeDB.BSATN.String + > NullableReferenceFieldRW = new(); + + public PublicTable Read(System.IO.BinaryReader reader) + { + var ___result = new PublicTable(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, PublicTable value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("Id", IdRW.GetAlgebraicType(registrar)), + new("ByteField", ByteFieldRW.GetAlgebraicType(registrar)), + new("UshortField", UshortFieldRW.GetAlgebraicType(registrar)), + new("UintField", UintFieldRW.GetAlgebraicType(registrar)), + new("UlongField", UlongFieldRW.GetAlgebraicType(registrar)), + new("UInt128Field", UInt128FieldRW.GetAlgebraicType(registrar)), + new("U128Field", U128FieldRW.GetAlgebraicType(registrar)), + new("U256Field", U256FieldRW.GetAlgebraicType(registrar)), + new("SbyteField", SbyteFieldRW.GetAlgebraicType(registrar)), + new("ShortField", ShortFieldRW.GetAlgebraicType(registrar)), + new("IntField", IntFieldRW.GetAlgebraicType(registrar)), + new("LongField", LongFieldRW.GetAlgebraicType(registrar)), + new("Int128Field", Int128FieldRW.GetAlgebraicType(registrar)), + new("I128Field", I128FieldRW.GetAlgebraicType(registrar)), + new("I256Field", I256FieldRW.GetAlgebraicType(registrar)), + new("BoolField", BoolFieldRW.GetAlgebraicType(registrar)), + new("FloatField", FloatFieldRW.GetAlgebraicType(registrar)), + new("DoubleField", DoubleFieldRW.GetAlgebraicType(registrar)), + new("StringField", StringFieldRW.GetAlgebraicType(registrar)), + new("IdentityField", IdentityFieldRW.GetAlgebraicType(registrar)), + new("ConnectionIdField", ConnectionIdFieldRW.GetAlgebraicType(registrar)), + new("CustomStructField", CustomStructFieldRW.GetAlgebraicType(registrar)), + new("CustomClassField", CustomClassFieldRW.GetAlgebraicType(registrar)), + new("CustomEnumField", CustomEnumFieldRW.GetAlgebraicType(registrar)), + new( + "CustomTaggedEnumField", + CustomTaggedEnumFieldRW.GetAlgebraicType(registrar) + ), + new("ListField", ListFieldRW.GetAlgebraicType(registrar)), + new("NullableValueField", NullableValueFieldRW.GetAlgebraicType(registrar)), + new( + "NullableReferenceField", + NullableReferenceFieldRW.GetAlgebraicType(registrar) + ), + } + )); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashId = Id.GetHashCode(); + var ___hashByteField = ByteField.GetHashCode(); + var ___hashUshortField = UshortField.GetHashCode(); + var ___hashUintField = UintField.GetHashCode(); + var ___hashUlongField = UlongField.GetHashCode(); + var ___hashUInt128Field = UInt128Field.GetHashCode(); + var ___hashU128Field = U128Field.GetHashCode(); + var ___hashU256Field = U256Field.GetHashCode(); + var ___hashSbyteField = SbyteField.GetHashCode(); + var ___hashShortField = ShortField.GetHashCode(); + var ___hashIntField = IntField.GetHashCode(); + var ___hashLongField = LongField.GetHashCode(); + var ___hashInt128Field = Int128Field.GetHashCode(); + var ___hashI128Field = I128Field.GetHashCode(); + var ___hashI256Field = I256Field.GetHashCode(); + var ___hashBoolField = BoolField.GetHashCode(); + var ___hashFloatField = FloatField.GetHashCode(); + var ___hashDoubleField = DoubleField.GetHashCode(); + var ___hashStringField = StringField == null ? 0 : StringField.GetHashCode(); + var ___hashIdentityField = IdentityField.GetHashCode(); + var ___hashConnectionIdField = ConnectionIdField.GetHashCode(); + var ___hashCustomStructField = CustomStructField.GetHashCode(); + var ___hashCustomClassField = CustomClassField == null ? 0 : CustomClassField.GetHashCode(); + var ___hashCustomEnumField = CustomEnumField.GetHashCode(); + var ___hashCustomTaggedEnumField = + CustomTaggedEnumField == null ? 0 : CustomTaggedEnumField.GetHashCode(); + var ___hashListField = 0; + if (ListField != null) + { + var ___hc0 = new System.HashCode(); + for (int ___i0 = 0; ___i0 < ListField.Count; ___i0++) + { + var ___tmp0 = ListField[___i0]; + var ___out1 = ___tmp0.GetHashCode(); + ___hc0.Add(___out1); + } + ___hashListField = ___hc0.ToHashCode(); + } + var ___hashNullableValueField = NullableValueField.GetHashCode(); + var ___hashNullableReferenceField = + NullableReferenceField == null ? 0 : NullableReferenceField.GetHashCode(); + return ___hashId + ^ ___hashByteField + ^ ___hashUshortField + ^ ___hashUintField + ^ ___hashUlongField + ^ ___hashUInt128Field + ^ ___hashU128Field + ^ ___hashU256Field + ^ ___hashSbyteField + ^ ___hashShortField + ^ ___hashIntField + ^ ___hashLongField + ^ ___hashInt128Field + ^ ___hashI128Field + ^ ___hashI256Field + ^ ___hashBoolField + ^ ___hashFloatField + ^ ___hashDoubleField + ^ ___hashStringField + ^ ___hashIdentityField + ^ ___hashConnectionIdField + ^ ___hashCustomStructField + ^ ___hashCustomClassField + ^ ___hashCustomEnumField + ^ ___hashCustomTaggedEnumField + ^ ___hashListField + ^ ___hashNullableValueField + ^ ___hashNullableReferenceField; + } + +#nullable enable + public bool Equals(PublicTable that) + { + var ___eqId = this.Id.Equals(that.Id); + var ___eqByteField = this.ByteField.Equals(that.ByteField); + var ___eqUshortField = this.UshortField.Equals(that.UshortField); + var ___eqUintField = this.UintField.Equals(that.UintField); + var ___eqUlongField = this.UlongField.Equals(that.UlongField); + var ___eqUInt128Field = this.UInt128Field.Equals(that.UInt128Field); + var ___eqU128Field = this.U128Field.Equals(that.U128Field); + var ___eqU256Field = this.U256Field.Equals(that.U256Field); + var ___eqSbyteField = this.SbyteField.Equals(that.SbyteField); + var ___eqShortField = this.ShortField.Equals(that.ShortField); + var ___eqIntField = this.IntField.Equals(that.IntField); + var ___eqLongField = this.LongField.Equals(that.LongField); + var ___eqInt128Field = this.Int128Field.Equals(that.Int128Field); + var ___eqI128Field = this.I128Field.Equals(that.I128Field); + var ___eqI256Field = this.I256Field.Equals(that.I256Field); + var ___eqBoolField = this.BoolField.Equals(that.BoolField); + var ___eqFloatField = this.FloatField.Equals(that.FloatField); + var ___eqDoubleField = this.DoubleField.Equals(that.DoubleField); + var ___eqStringField = + this.StringField == null + ? that.StringField == null + : this.StringField.Equals(that.StringField); + var ___eqIdentityField = this.IdentityField.Equals(that.IdentityField); + var ___eqConnectionIdField = this.ConnectionIdField.Equals(that.ConnectionIdField); + var ___eqCustomStructField = this.CustomStructField.Equals(that.CustomStructField); + var ___eqCustomClassField = + this.CustomClassField == null + ? that.CustomClassField == null + : this.CustomClassField.Equals(that.CustomClassField); + var ___eqCustomEnumField = this.CustomEnumField == that.CustomEnumField; + var ___eqCustomTaggedEnumField = + this.CustomTaggedEnumField == null + ? that.CustomTaggedEnumField == null + : this.CustomTaggedEnumField.Equals(that.CustomTaggedEnumField); + var ___eqListField = true; + if (this.ListField == null || that.ListField == null) + { + ___eqListField = this.ListField == that.ListField; + } + else if (this.ListField.Count != that.ListField.Count) + { + ___eqListField = false; + } + else + { + for (int ___i0 = 0; ___i0 < this.ListField.Count; ___i0++) + { + var ___tmpA0 = this.ListField[___i0]; + var ___tmpB0 = that.ListField[___i0]; + var ___out1 = ___tmpA0.Equals(___tmpB0); + if (!___out1) + { + ___eqListField = false; + break; + } + } + } + var ___eqNullableValueField = System.Nullable.Equals( + this.NullableValueField, + that.NullableValueField + ); + var ___eqNullableReferenceField = + this.NullableReferenceField == null + ? that.NullableReferenceField == null + : this.NullableReferenceField.Equals(that.NullableReferenceField); + return ___eqId + && ___eqByteField + && ___eqUshortField + && ___eqUintField + && ___eqUlongField + && ___eqUInt128Field + && ___eqU128Field + && ___eqU256Field + && ___eqSbyteField + && ___eqShortField + && ___eqIntField + && ___eqLongField + && ___eqInt128Field + && ___eqI128Field + && ___eqI256Field + && ___eqBoolField + && ___eqFloatField + && ___eqDoubleField + && ___eqStringField + && ___eqIdentityField + && ___eqConnectionIdField + && ___eqCustomStructField + && ___eqCustomClassField + && ___eqCustomEnumField + && ___eqCustomTaggedEnumField + && ___eqListField + && ___eqNullableValueField + && ___eqNullableReferenceField; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as PublicTable?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(PublicTable this_, PublicTable that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(PublicTable this_, PublicTable that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // PublicTable diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.InsertData.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.InsertData.verified.cs new file mode 100644 index 00000000000..52cdd4b59ac --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.InsertData.verified.cs @@ -0,0 +1,21 @@ +//HintName: Reducers.InsertData.cs +// +#nullable enable + +partial class Reducers +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateInsertData(PublicTable data) + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new PublicTable.BSATN().Write(writer, data); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(InsertData) + ), + stream + ); + } +} // Reducers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.ScheduleImmediate.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.ScheduleImmediate.verified.cs new file mode 100644 index 00000000000..5f3498a3fbe --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.ScheduleImmediate.verified.cs @@ -0,0 +1,21 @@ +//HintName: Reducers.ScheduleImmediate.cs +// +#nullable enable + +partial class Reducers +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateScheduleImmediate(PublicTable data) + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new PublicTable.BSATN().Write(writer, data); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(ScheduleImmediate) + ), + stream + ); + } +} // Reducers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#RegressionMultipleUniqueIndexesHadSameName.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#RegressionMultipleUniqueIndexesHadSameName.verified.cs new file mode 100644 index 00000000000..08d5589debd --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#RegressionMultipleUniqueIndexesHadSameName.verified.cs @@ -0,0 +1,121 @@ +//HintName: RegressionMultipleUniqueIndexesHadSameName.cs +// +#nullable enable + +partial struct RegressionMultipleUniqueIndexesHadSameName + : System.IEquatable, + SpacetimeDB.BSATN.IStructuralReadWrite +{ + public void ReadFields(System.IO.BinaryReader reader) + { + Unique1 = BSATN.Unique1RW.Read(reader); + Unique2 = BSATN.Unique2RW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) + { + BSATN.Unique1RW.Write(writer, Unique1); + BSATN.Unique2RW.Write(writer, Unique2); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => + $"RegressionMultipleUniqueIndexesHadSameName {{ Unique1 = {SpacetimeDB.BSATN.StringUtil.GenericToString(Unique1)}, Unique2 = {SpacetimeDB.BSATN.StringUtil.GenericToString(Unique2)} }}"; + + public readonly partial struct BSATN + : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.U32 Unique1RW = new(); + internal static readonly SpacetimeDB.BSATN.U32 Unique2RW = new(); + + public RegressionMultipleUniqueIndexesHadSameName Read(System.IO.BinaryReader reader) + { + var ___result = new RegressionMultipleUniqueIndexesHadSameName(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write( + System.IO.BinaryWriter writer, + RegressionMultipleUniqueIndexesHadSameName value + ) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType( + _ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("Unique1", Unique1RW.GetAlgebraicType(registrar)), + new("Unique2", Unique2RW.GetAlgebraicType(registrar)), + } + ) + ); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashUnique1 = Unique1.GetHashCode(); + var ___hashUnique2 = Unique2.GetHashCode(); + return ___hashUnique1 ^ ___hashUnique2; + } + +#nullable enable + public bool Equals(RegressionMultipleUniqueIndexesHadSameName that) + { + var ___eqUnique1 = this.Unique1.Equals(that.Unique1); + var ___eqUnique2 = this.Unique2.Equals(that.Unique2); + return ___eqUnique1 && ___eqUnique2; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as RegressionMultipleUniqueIndexesHadSameName?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==( + RegressionMultipleUniqueIndexesHadSameName this_, + RegressionMultipleUniqueIndexesHadSameName that + ) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=( + RegressionMultipleUniqueIndexesHadSameName this_, + RegressionMultipleUniqueIndexesHadSameName that + ) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // RegressionMultipleUniqueIndexesHadSameName diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs new file mode 100644 index 00000000000..5fc1e766688 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs @@ -0,0 +1,24 @@ +//HintName: Test.NestingNamespaces.AndClasses.InsertData2.cs +// +#nullable enable + +namespace Test.NestingNamespaces +{ + partial class AndClasses + { + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateInsertData2(PublicTable data) + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new PublicTable.BSATN().Write(writer, data); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(InsertData2) + ), + stream + ); + } + } // AndClasses +} // namespace diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.Init.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.Init.verified.cs new file mode 100644 index 00000000000..61a3f46c69d --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.Init.verified.cs @@ -0,0 +1,21 @@ +//HintName: Timers.Init.cs +// +#nullable enable + +partial class Timers +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateInit() + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(Init) + ), + stream + ); + } +} // Timers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendMessageTimer.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendMessageTimer.verified.cs new file mode 100644 index 00000000000..90065b14a30 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendMessageTimer.verified.cs @@ -0,0 +1,123 @@ +//HintName: Timers.SendMessageTimer.cs +// +#nullable enable + +partial class Timers +{ + partial struct SendMessageTimer + : System.IEquatable, + SpacetimeDB.BSATN.IStructuralReadWrite + { + public void ReadFields(System.IO.BinaryReader reader) + { + ScheduledId = BSATN.ScheduledIdRW.Read(reader); + ScheduledAt = BSATN.ScheduledAtRW.Read(reader); + Text = BSATN.TextRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) + { + BSATN.ScheduledIdRW.Write(writer, ScheduledId); + BSATN.ScheduledAtRW.Write(writer, ScheduledAt); + BSATN.TextRW.Write(writer, Text); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() + { + return new BSATN(); + } + + public override string ToString() => + $"SendMessageTimer {{ ScheduledId = {SpacetimeDB.BSATN.StringUtil.GenericToString(ScheduledId)}, ScheduledAt = {SpacetimeDB.BSATN.StringUtil.GenericToString(ScheduledAt)}, Text = {SpacetimeDB.BSATN.StringUtil.GenericToString(Text)} }}"; + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.U64 ScheduledIdRW = new(); + internal static readonly SpacetimeDB.ScheduleAt.BSATN ScheduledAtRW = new(); + internal static readonly SpacetimeDB.BSATN.String TextRW = new(); + + public Timers.SendMessageTimer Read(System.IO.BinaryReader reader) + { + var ___result = new Timers.SendMessageTimer(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, Timers.SendMessageTimer value) + { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => + registrar.RegisterType( + _ => new SpacetimeDB.BSATN.AlgebraicType.Product( + new SpacetimeDB.BSATN.AggregateElement[] + { + new("ScheduledId", ScheduledIdRW.GetAlgebraicType(registrar)), + new("ScheduledAt", ScheduledAtRW.GetAlgebraicType(registrar)), + new("Text", TextRW.GetAlgebraicType(registrar)), + } + ) + ); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType( + SpacetimeDB.BSATN.ITypeRegistrar registrar + ) => GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashScheduledId = ScheduledId.GetHashCode(); + var ___hashScheduledAt = ScheduledAt == null ? 0 : ScheduledAt.GetHashCode(); + var ___hashText = Text == null ? 0 : Text.GetHashCode(); + return ___hashScheduledId ^ ___hashScheduledAt ^ ___hashText; + } + +#nullable enable + public bool Equals(Timers.SendMessageTimer that) + { + var ___eqScheduledId = this.ScheduledId.Equals(that.ScheduledId); + var ___eqScheduledAt = + this.ScheduledAt == null + ? that.ScheduledAt == null + : this.ScheduledAt.Equals(that.ScheduledAt); + var ___eqText = this.Text == null ? that.Text == null : this.Text.Equals(that.Text); + return ___eqScheduledId && ___eqScheduledAt && ___eqText; + } + + public override bool Equals(object? that) + { + if (that == null) + { + return false; + } + var that_ = that as Timers.SendMessageTimer?; + if (((object?)that_) == null) + { + return false; + } + return Equals(that_); + } + + public static bool operator ==(Timers.SendMessageTimer this_, Timers.SendMessageTimer that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator !=(Timers.SendMessageTimer this_, Timers.SendMessageTimer that) + { + if (((object?)this_) == null || ((object?)that) == null) + { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore + } // SendMessageTimer +} // Timers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendScheduledMessage.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendScheduledMessage.verified.cs new file mode 100644 index 00000000000..04376ee92b9 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendScheduledMessage.verified.cs @@ -0,0 +1,23 @@ +//HintName: Timers.SendScheduledMessage.cs +// +#nullable enable + +partial class Timers +{ + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] + public static void VolatileNonatomicScheduleImmediateSendScheduledMessage( + Timers.SendMessageTimer arg + ) + { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new Timers.SendMessageTimer.BSATN().Write(writer, arg); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(SendScheduledMessage) + ), + stream + ); + } +} // Timers diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#ContainsNestedLists.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#ContainsNestedLists.verified.cs index 87362d50f8c..7d1f84bf4e8 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#ContainsNestedLists.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#ContainsNestedLists.verified.cs @@ -110,7 +110,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new( "StringListListArray", StringListListArrayRW.GetAlgebraicType(registrar) - ) + ), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomClass.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomClass.verified.cs index fd03fc1c88c..747b4e001ba 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomClass.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomClass.verified.cs @@ -62,7 +62,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new("IntField", IntFieldRW.GetAlgebraicType(registrar)), new("StringField", StringFieldRW.GetAlgebraicType(registrar)), new("NullableIntField", NullableIntFieldRW.GetAlgebraicType(registrar)), - new("NullableStringField", NullableStringFieldRW.GetAlgebraicType(registrar)) + new("NullableStringField", NullableStringFieldRW.GetAlgebraicType(registrar)), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomNestedClass.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomNestedClass.verified.cs index f713b9b01ac..0bb9a731fc6 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomNestedClass.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomNestedClass.verified.cs @@ -96,7 +96,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new( "NestedNullableCustomRecord", NestedNullableCustomRecordRW.GetAlgebraicType(registrar) - ) + ), } ) ); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomRecord.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomRecord.verified.cs index f75ef133e9e..0e812263dec 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomRecord.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomRecord.verified.cs @@ -62,7 +62,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new("IntField", IntFieldRW.GetAlgebraicType(registrar)), new("StringField", StringFieldRW.GetAlgebraicType(registrar)), new("NullableIntField", NullableIntFieldRW.GetAlgebraicType(registrar)), - new("NullableStringField", NullableStringFieldRW.GetAlgebraicType(registrar)) + new("NullableStringField", NullableStringFieldRW.GetAlgebraicType(registrar)), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomStruct.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomStruct.verified.cs index 56afcdd431c..fb4ef83d788 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomStruct.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomStruct.verified.cs @@ -64,7 +64,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new("IntField", IntFieldRW.GetAlgebraicType(registrar)), new("StringField", StringFieldRW.GetAlgebraicType(registrar)), new("NullableIntField", NullableIntFieldRW.GetAlgebraicType(registrar)), - new("NullableStringField", NullableStringFieldRW.GetAlgebraicType(registrar)) + new("NullableStringField", NullableStringFieldRW.GetAlgebraicType(registrar)), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomTaggedEnum.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomTaggedEnum.verified.cs index 78c43d2fb53..01ec183af3e 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomTaggedEnum.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#CustomTaggedEnum.verified.cs @@ -49,10 +49,9 @@ public CustomTaggedEnum Read(System.IO.BinaryReader reader) 1 => new StringVariant(StringVariantRW.Read(reader)), 2 => new NullableIntVariant(NullableIntVariantRW.Read(reader)), 3 => new NullableStringVariant(NullableStringVariantRW.Read(reader)), - _ - => throw new System.InvalidOperationException( - "Invalid tag value, this state should be unreachable." - ) + _ => throw new System.InvalidOperationException( + "Invalid tag value, this state should be unreachable." + ), }; } @@ -91,7 +90,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar new( "NullableStringVariant", NullableStringVariantRW.GetAlgebraicType(registrar) - ) + ), } )); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#FormerlyForbiddenFieldNames.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#FormerlyForbiddenFieldNames.verified.cs index 8c9d2c5f5b0..3b143e46d48 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#FormerlyForbiddenFieldNames.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Type#FormerlyForbiddenFieldNames.verified.cs @@ -55,7 +55,7 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar { new("Read", ReadRW.GetAlgebraicType(registrar)), new("Write", WriteRW.GetAlgebraicType(registrar)), - new("GetAlgebraicType", GetAlgebraicTypeRW.GetAlgebraicType(registrar)) + new("GetAlgebraicType", GetAlgebraicTypeRW.GetAlgebraicType(registrar)), } ) ); diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt index 5ae3339cfaa..f961e0c49e4 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=LegacySubscribeAll.verified.txt @@ -106,10 +106,12 @@ }, Db: { Message: { + RemoteTableName: message, Count: 4 }, User: { Identity: {}, + RemoteTableName: user, Count: 3 } }, @@ -138,10 +140,12 @@ }, Db: { Message: { + RemoteTableName: message, Count: 4 }, User: { Identity: {}, + RemoteTableName: user, Count: 3 } }, @@ -170,10 +174,12 @@ }, Db: { Message: { + RemoteTableName: message, Count: 4 }, User: { Identity: {}, + RemoteTableName: user, Count: 3 } }, diff --git a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt index 7dd87750886..1cefa360546 100644 --- a/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt +++ b/sdks/csharp/tests~/SnapshotTests.VerifySampleDump_dumpName=SubscribeApplied.verified.txt @@ -106,10 +106,12 @@ }, Db: { Message: { + RemoteTableName: message, Count: 4 }, User: { Identity: {}, + RemoteTableName: user, Count: 3 } }, @@ -138,10 +140,12 @@ }, Db: { Message: { + RemoteTableName: message, Count: 4 }, User: { Identity: {}, + RemoteTableName: user, Count: 3 } }, From ce10ad192d8640caeb1f8b10688507982c33d3e0 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Fri, 18 Sep 2026 09:57:56 -0500 Subject: [PATCH 15/49] Test root-defined RLS rule targeting table in submodule --- modules/namespace-test-cs/Lib.cs | 23 +++ .../libraries/AuthLib/Lib.cs | 9 + .../regression-tests/namespaces/Program.cs | 1 + .../regression-tests/namespaces/README.md | 3 + .../namespaces/RootRlsTests.cs | 182 ++++++++++++++++++ .../module_bindings/MyAuth/Namespace.g.cs | 2 + .../MyAuth/Tables/ProtectedRow.g.cs | 64 ++++++ .../MyAuth/Types/ProtectedRow.g.cs | 38 ++++ .../Reducers/WriteProtectedRow.g.cs | 78 ++++++++ .../module_bindings/SpacetimeDBClient.g.cs | 2 + 10 files changed, 402 insertions(+) create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/RootRlsTests.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ProtectedRow.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/WriteProtectedRow.g.cs diff --git a/modules/namespace-test-cs/Lib.cs b/modules/namespace-test-cs/Lib.cs index f82b9df6ad5..d42e6c75b0b 100644 --- a/modules/namespace-test-cs/Lib.cs +++ b/modules/namespace-test-cs/Lib.cs @@ -20,6 +20,29 @@ public partial struct AuthSummary public static partial class Functions { +#pragma warning disable STDB_UNSTABLE + [ClientVisibilityFilter] + public static readonly Filter ProtectedRows = new Filter.Sql( + "SELECT * FROM \"MyAuth\".protected_row WHERE owner = :sender" + ); +#pragma warning restore STDB_UNSTABLE + + // Test setup deliberately permits writing for either client; RLS restricts reads, not reducers. + [Reducer] + public static void WriteProtectedRow(ReducerContext ctx, uint id, Identity owner, uint value) + { + var row = new AuthLib.ProtectedRow + { + Id = id, + Owner = owner, + Value = value, + }; + if (ctx.Db.MyAuth.ProtectedRow.Id.Find(id) is null) + ctx.Db.MyAuth.ProtectedRow.Insert(row); + else + ctx.Db.MyAuth.ProtectedRow.Id.Update(row); + } + [Reducer] public static void Exercise(ReducerContext ctx) { diff --git a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs index 470c08a0133..a530c749c32 100644 --- a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs +++ b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs @@ -6,6 +6,15 @@ namespace AuthLib; public class Marker { } +[Table(Accessor = "ProtectedRow", Public = true)] +public partial struct ProtectedRow +{ + [PrimaryKey] + public uint Id; + public Identity Owner; + public uint Value; +} + [Table(Accessor = "User", Name = "auth_users", Public = true)] [SpacetimeDB.Index.BTree(Accessor = "ByScore", Columns = [nameof(Score)])] public partial struct User diff --git a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs index 69e507dece5..75d82fbf800 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs @@ -528,6 +528,7 @@ void CheckTransactionInsert(EventContext ctx, uint id) ); Unsubscribe(all); EmptyCache(); + RootRlsTests.Run(host); Console.WriteLine("Namespace integration passed"); } finally diff --git a/sdks/csharp/examples~/regression-tests/namespaces/README.md b/sdks/csharp/examples~/regression-tests/namespaces/README.md index 1ef7c06d6b8..ee18dc0e757 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/README.md +++ b/sdks/csharp/examples~/regression-tests/namespaces/README.md @@ -36,6 +36,9 @@ Coverage: callbacks, and child reducer failures forwarded to the root connection. - Insert/update/delete callbacks, unique/B-tree indexes, and reducer rollback. - Event rows, private-table access rejection, procedural/anonymous/query views. +- Root-defined RLS on a public namespaced table: two distinct non-owner clients, + typed/raw subscriptions, initial rows, live inserts/updates, ownership transfer, + filtered one-off queries, and unsubscribe cleanup. No library-defined RLS rules. - `RemoteQuery` result decoding and no subscription-cache population by one-off queries. - Subscribe-all initial rows, no replay of past events, and unsubscribe cache cleanup. - Same-named scheduled reducers/procedures in both namespaces, with explicit function diff --git a/sdks/csharp/examples~/regression-tests/namespaces/RootRlsTests.cs b/sdks/csharp/examples~/regression-tests/namespaces/RootRlsTests.cs new file mode 100644 index 00000000000..7227a9e2152 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/RootRlsTests.cs @@ -0,0 +1,182 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using SpacetimeDB; +using SpacetimeDB.Types; + +internal static class RootRlsTests +{ + private static void Require(bool condition, string message) + { + if (!condition) + throw new Exception(message); + } + + public static void Run(string host) + { + Identity? firstIdentity = null; + Identity? secondIdentity = null; + Exception? error = null; + var first = DbConnection + .Builder() + .WithUri(host) + .WithDatabaseName("namespace-tests") + .OnConnect((_, identity, _) => firstIdentity = identity) + .OnConnectError(e => error = e) + .Build(); + var second = DbConnection + .Builder() + .WithUri(host) + .WithDatabaseName("namespace-tests") + .OnConnect((_, identity, _) => secondIdentity = identity) + .OnConnectError(e => error = e) + .Build(); + + void Wait(Func done, string phase) + { + var timer = Stopwatch.StartNew(); + while (!done()) + { + if (error != null) + throw error; + if (timer.Elapsed > TimeSpan.FromSeconds(30)) + throw new TimeoutException("Root RLS: " + phase); + first.FrameTick(); + second.FrameTick(); + Thread.Sleep(5); + } + if (error != null) + throw error; + } + + try + { + Wait(() => firstIdentity != null && secondIdentity != null, "connect"); + var firstOwner = firstIdentity ?? throw new Exception("Missing first identity"); + var secondOwner = secondIdentity ?? throw new Exception("Missing second identity"); + Require(!firstOwner.Equals(secondOwner), "RLS clients must have distinct identities"); + var writes = 0; + first.Reducers.OnWriteProtectedRow += (ctx, _, _, _) => + { + Require(ctx.Event.Status is Status.Committed, "RLS fixture write failed"); + writes++; + }; + void Write(uint id, Identity owner, uint value) + { + var expected = writes + 1; + first.Reducers.WriteProtectedRow(id, owner, value); + Wait(() => writes == expected, "write"); + } + + Write(1, firstOwner, 10); + Write(2, secondOwner, 20); + + var inserts = new int[2]; + var updates = new int[2]; + var deletes = new int[2]; + var clients = new[] { first, second }; + var identities = new[] { firstOwner, secondOwner }; + for (var i = 0; i < clients.Length; i++) + { + var index = i; + clients[i].Db.MyAuth.ProtectedRow.OnInsert += (_, row) => + { + Require(row.Owner.Equals(identities[index]), "RLS leaked an insert"); + inserts[index]++; + }; + clients[i].Db.MyAuth.ProtectedRow.OnUpdate += (_, before, after) => + { + Require( + before.Owner.Equals(identities[index]) + && after.Owner.Equals(identities[index]), + "RLS leaked an update" + ); + updates[index]++; + }; + clients[i].Db.MyAuth.ProtectedRow.OnDelete += (_, row) => + { + Require(row.Owner.Equals(identities[index]), "RLS leaked a deletion"); + deletes[index]++; + }; + } + + var applied = 0; + var firstSub = first + .SubscriptionBuilder() + .OnApplied(_ => applied++) + .OnError((_, e) => error = e) + .AddQuery(q => q.From.MyAuth.ProtectedRow()) + .Subscribe(); + var secondSub = second + .SubscriptionBuilder() + .OnApplied(_ => applied++) + .OnError((_, e) => error = e) + .Subscribe(new[] { "SELECT * FROM \"MyAuth\".protected_row" }); + Wait(() => applied == 2, "initial subscriptions"); + Require(first.Db.MyAuth.ProtectedRow.Iter().Single().Id == 1, "First initial RLS rows"); + Require( + second.Db.MyAuth.ProtectedRow.Iter().Single().Id == 2, + "Second initial RLS rows" + ); + + Write(1, firstOwner, 11); + Write(2, secondOwner, 21); + Wait(() => updates[0] == 1 && updates[1] == 1, "visible updates"); + Require( + first.Db.MyAuth.ProtectedRow.Iter().Single().Value == 11, + "First updated value" + ); + Require( + second.Db.MyAuth.ProtectedRow.Iter().Single().Value == 21, + "Second updated value" + ); + + // Changing ownership must remove the old owner's row and insert it for the new owner. + Write(1, secondOwner, 12); + Wait(() => deletes[0] == 1 && inserts[1] == 2, "ownership transfer"); + Require(first.Db.MyAuth.ProtectedRow.Count == 0, "Old owner retained the row"); + Require(second.Db.MyAuth.ProtectedRow.Count == 2, "New owner did not receive the row"); + Write(3, firstOwner, 30); + Wait(() => inserts[0] == 2, "live insert"); + + var firstQuery = first.Db.MyAuth.ProtectedRow.RemoteQuery(""); + var secondQuery = second.Db.MyAuth.ProtectedRow.RemoteQuery(""); + Wait(() => firstQuery.IsCompleted && secondQuery.IsCompleted, "filtered RemoteQuery"); + Require(firstQuery.GetAwaiter().GetResult().Single().Id == 3, "First RemoteQuery RLS"); + Require( + secondQuery + .GetAwaiter() + .GetResult() + .Select(row => row.Id) + .OrderBy(id => id) + .SequenceEqual(new uint[] { 1, 2 }), + "Second RemoteQuery RLS" + ); + Require( + inserts[0] == 2 + && inserts[1] == 2 + && updates[0] == 1 + && updates[1] == 1 + && deletes[0] == 1 + && deletes[1] == 0, + "Hidden changes must not produce callbacks" + ); + + var unsubscribed = 0; + firstSub.UnsubscribeThen(_ => unsubscribed++); + secondSub.UnsubscribeThen(_ => unsubscribed++); + Wait(() => unsubscribed == 2, "unsubscribe"); + Require( + first.Db.MyAuth.ProtectedRow.Count == 0 && second.Db.MyAuth.ProtectedRow.Count == 0, + "RLS unsubscribe must clear both caches" + ); + Console.WriteLine("Root-defined RLS on a namespace table passed"); + } + finally + { + first.Disconnect(); + second.Disconnect(); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs index a4f5e918e69..a1bbea5e3df 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs @@ -25,6 +25,7 @@ internal RemoteTables(global::SpacetimeDB.Types.DbConnection conn, Action AnonymousUsers() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users"), new AnonymousUsersCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users")), new AnonymousUsersIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users"))); public global::SpacetimeDB.Table Notice() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice"), new NoticeCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice")), new NoticeIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice"))); + public global::SpacetimeDB.Table ProtectedRow() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "protected_row"), new ProtectedRowCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "protected_row")), new ProtectedRowIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "protected_row"))); public global::SpacetimeDB.Table QueryUsers() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users"), new QueryUsersCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users")), new QueryUsersIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users"))); public global::SpacetimeDB.Table ScheduleResult() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "schedule_result"), new ScheduleResultCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "schedule_result")), new ScheduleResultIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "schedule_result"))); public global::SpacetimeDB.Table User() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users"), new UserCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users")), new UserIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users"))); diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs new file mode 100644 index 00000000000..a3a8179df79 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteTables + { + public sealed class ProtectedRowHandle : RemoteTableHandle + { + public override string RemoteTableName => "MyAuth.protected_row"; + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "protected_row"); + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override uint GetKey(ProtectedRow row) => row.Id; + + public IdUniqueIndex(ProtectedRowHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + internal ProtectedRowHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) + { + Id = new(this); + } + + protected override object GetPrimaryKey(ProtectedRow row) => row.Id; + } + + public readonly ProtectedRowHandle ProtectedRow; + } + + public sealed class ProtectedRowCols + { + public global::SpacetimeDB.Col Id { get; } + public global::SpacetimeDB.Col Owner { get; } + public global::SpacetimeDB.Col Value { get; } + + public ProtectedRowCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + Owner = new global::SpacetimeDB.Col(tableName, "owner"); + Value = new global::SpacetimeDB.Col(tableName, "value"); + } + } + + public sealed class ProtectedRowIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + + public ProtectedRowIxCols(global::SpacetimeDB.SqlTableName tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ProtectedRow.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ProtectedRow.g.cs new file mode 100644 index 00000000000..a587ca613be --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Types/ProtectedRow.g.cs @@ -0,0 +1,38 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ProtectedRow + { + [DataMember(Name = "id")] + public uint Id; + [DataMember(Name = "owner")] + public SpacetimeDB.Identity Owner; + [DataMember(Name = "value")] + public uint Value; + + public ProtectedRow( + uint Id, + SpacetimeDB.Identity Owner, + uint Value + ) + { + this.Id = Id; + this.Owner = Owner; + this.Value = Value; + } + + public ProtectedRow() + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/WriteProtectedRow.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/WriteProtectedRow.g.cs new file mode 100644 index 00000000000..497e6dd8f7f --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/WriteProtectedRow.g.cs @@ -0,0 +1,78 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void WriteProtectedRowHandler(ReducerEventContext ctx, uint id, SpacetimeDB.Identity owner, uint value); + public event WriteProtectedRowHandler? OnWriteProtectedRow; + + public void WriteProtectedRow(uint id, SpacetimeDB.Identity owner, uint value) + { + conn.InternalCallReducer(new Reducer.WriteProtectedRow(id, owner, value)); + } + + public bool InvokeWriteProtectedRow(ReducerEventContext ctx, Reducer.WriteProtectedRow args) + { + if (OnWriteProtectedRow == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnWriteProtectedRow( + ctx, + args.Id, + args.Owner, + args.Value + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class WriteProtectedRow : Reducer, IReducerArgs + { + [DataMember(Name = "id")] + public uint Id; + [DataMember(Name = "owner")] + public SpacetimeDB.Identity Owner; + [DataMember(Name = "value")] + public uint Value; + + public WriteProtectedRow( + uint Id, + SpacetimeDB.Identity Owner, + uint Value + ) + { + this.Id = Id; + this.Owner = Owner; + this.Value = Value; + } + + public WriteProtectedRow() + { + } + + string IReducerArgs.ReducerName => "write_protected_row"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs index 2e605f8ef57..9fd4f2dd7bd 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs @@ -558,6 +558,7 @@ public sealed class QueryBuilder new QueryBuilder().From.User().ToSql(), new QueryBuilder().From.Users().ToSql(), new QueryBuilder().From.@MyAuth.Notice().ToSql(), + new QueryBuilder().From.@MyAuth.ProtectedRow().ToSql(), new QueryBuilder().From.@MyAuth.ScheduleResult().ToSql(), new QueryBuilder().From.@MyAuth.User().ToSql(), new QueryBuilder().From.@class.ScheduleResult().ToSql(), @@ -663,6 +664,7 @@ protected override bool Dispatch(IReducerEventContext context, Reducer reducer) return reducer switch { Reducer.Exercise args => Reducers.InvokeExercise(eventContext, args), + Reducer.WriteProtectedRow args => Reducers.InvokeWriteProtectedRow(eventContext, args), Reducer.Extra args => Reducers.InvokeExtra(eventContext, args), global::SpacetimeDB.Types.@class.Reducer.Add args => Reducers.@class.InvokeAdd(eventContext, args), global::SpacetimeDB.Types.@class.Reducer.CancelSchedules args => Reducers.@class.InvokeCancelSchedules(eventContext, args), From 28585a0592892fae49074d20eb7ceba1330ddc8a Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Mon, 21 Sep 2026 09:55:45 -0500 Subject: [PATCH 16/49] Handle env variables with the new ModuleBuilder --- .../Codegen.Tests/EnvironmentTests.cs | 58 +++++++++++- crates/bindings-csharp/Codegen.Tests/Tests.cs | 88 +++++++++++++++++-- .../ExtraCompilationErrors.net10.verified.txt | 12 +-- .../snapshots/Module.net10#FFI.verified.cs | 9 ++ .../snapshots/Module.net10#FFI.verified.cs | 9 ++ .../Codegen.Tests/fixtures/server/Lib.cs | 9 ++ ...ronmentGenerator#Environment.g.verified.cs | 46 ++++++++++ ...tGenerator.net10#Environment.g.verified.cs | 23 +++++ .../snapshots/Module.net10#FFI.verified.cs | 25 +++++- crates/bindings-csharp/Codegen/Environment.cs | 80 ++++++++++++++--- crates/bindings-csharp/Codegen/Module.cs | 23 +++-- crates/bindings-csharp/README.md | 7 ++ .../Runtime/Internal/ModuleBuilder.cs | 2 +- .../bindings-csharp/Runtime/ModuleContexts.cs | 3 + .../tests/standalone_integration_test.rs | 9 ++ modules/namespace-test-cs/Lib.cs | 20 +++++ .../libraries/AuthLib/Lib.cs | 4 + .../regression-tests/namespaces/Program.cs | 16 +++- .../regression-tests/namespaces/README.md | 2 + .../MyAuth/Procedures/ReadEnvironment.g.cs | 65 ++++++++++++++ .../Procedures/ReadEnvironment.g.cs | 65 ++++++++++++++ .../module_bindings/SpacetimeDBClient.g.cs | 2 +- 22 files changed, 540 insertions(+), 37 deletions(-) create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/EnvironmentGenerator#Environment.g.verified.cs create mode 100644 crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/EnvironmentGenerator.net10#Environment.g.verified.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadEnvironment.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/ReadEnvironment.g.cs diff --git a/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs b/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs index d3564f218ae..0af40264494 100644 --- a/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs +++ b/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs @@ -47,13 +47,17 @@ public static class Module { """; private static (Compilation Compilation, GeneratorDriverRunResult Result) Generate( - string declaration + string declaration, + bool sharedContexts = false ) { var references = ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES")!) .Split(Path.PathSeparator) .Select(path => MetadataReference.CreateFromFile(path)); - var parse = new CSharpParseOptions(LanguageVersion.Preview); + var parse = new CSharpParseOptions( + LanguageVersion.Preview, + preprocessorSymbols: sharedContexts ? ["NET10_0_OR_GREATER"] : [] + ); var compilation = CSharpCompilation.Create( "EnvironmentFixture" + Guid.NewGuid().ToString("N"), [CSharpSyntaxTree.ParseText(Host + declaration, parse)], @@ -65,9 +69,59 @@ [new EnvironmentGenerator().AsSourceGenerator()], parseOptions: parse ); driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var output, out _); + if (sharedContexts) + { + var generatedNamespace = driver + .GetRunResult() + .GeneratedTrees.Single() + .GetRoot() + .DescendantNodes() + .OfType() + .Single() + .Name; + output = output.AddSyntaxTrees( + CSharpSyntaxTree.ParseText("global using " + generatedNamespace + ";", parse) + ); + } return (output, driver.GetRunResult()); } +#if NET10_0_OR_GREATER + [Fact] + public static void SharedReceiverAccessorsKeepCheckedLiveReads() + { + var (compilation, result) = Generate( + """ + [SpacetimeDB.Env] public struct Declarations { + public string REQUIRED; + public string OPTIONAL; + [SpacetimeDB.EnvValues("prod", "dev")] public string MODE; + public string @class; + } + public static class Usage { + public static void Check() { + if (SpacetimeDB.Internal.Module.Declarations.Count != 0) + throw new System.Exception("environment registered before descriptor call"); + var env = new SpacetimeDB.DatabaseEnvironment(); + if (env.REQUIRED == env.REQUIRED || env.MODE != "prod" || env.@class != "keyword") + throw new System.Exception("bad shared accessor"); + try { _ = env.OPTIONAL; throw new System.Exception("missing required value accepted"); } + catch (System.InvalidOperationException) {} + try { env.Get("UNKNOWN"); throw new System.Exception("unchecked read"); } + catch (System.InvalidOperationException) {} + } + } + """, + sharedContexts: true + ); + Assert.Empty(result.Diagnostics); + using var stream = new MemoryStream(); + var emitted = compilation.Emit(stream); + Assert.True(emitted.Success, string.Join("\n", emitted.Diagnostics)); + Assembly.Load(stream.ToArray()).GetType("Usage")!.GetMethod("Check")!.Invoke(null, null); + } +#endif + [Fact] public static void NamedAccessorsKeepCheckedReadsAndRegisterCanonicalConstraints() { diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index ad794219ec6..7dde87ea7cf 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -52,7 +52,7 @@ public static async Task Compile(string name, string? targetFramework = public Task Verify(string fileName, object target) { - if ((fileName == nameof(Module) || fileName == "ExtraCompilationErrors") + if ((fileName == nameof(Module) || fileName == nameof(EnvironmentGenerator) || fileName == "ExtraCompilationErrors") && ModuleTargetFramework == "net10.0") { fileName += ".net10"; @@ -268,6 +268,7 @@ public static async Task NamespaceProofPreservesNet8RootExamples() { new SpacetimeDB.Codegen.Type(), new SpacetimeDB.Codegen.Module(), + new EnvironmentGenerator(), } ) { @@ -287,7 +288,7 @@ public static async Task FormattedGeneratedCodeCompiles(string fixtureName) { var fixture = await Fixture.Compile(fixtureName); var compilation = fixture.SampleCompilation; - foreach (var generator in new IIncrementalGenerator[] { new Type(), new Module() }) + foreach (var generator in new IIncrementalGenerator[] { new Type(), new Module(), new EnvironmentGenerator() }) { foreach (var tree in fixture.RunGeneratorAndGetResult(generator).GeneratedTrees) { @@ -334,7 +335,7 @@ public static void ProcedureTick(SpacetimeDB.ProcedureContext ctx, uint payload) new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) ); var driver = CSharpGeneratorDriver.Create( - [new Type().AsSourceGenerator(), new Module().AsSourceGenerator()], + [new Type().AsSourceGenerator(), new Module().AsSourceGenerator(), new EnvironmentGenerator().AsSourceGenerator()], parseOptions: fixture.ParseOptions ); driver.RunGeneratorsAndUpdateCompilation(input, out var output, out var diagnostics); @@ -390,7 +391,7 @@ public partial struct Row { public uint Id; } } """); var driver = CSharpGeneratorDriver.Create( - [new Type().AsSourceGenerator(), new Module().AsSourceGenerator()], + [new Type().AsSourceGenerator(), new Module().AsSourceGenerator(), new EnvironmentGenerator().AsSourceGenerator()], parseOptions: fixture.ParseOptions ); driver.RunGeneratorsAndUpdateCompilation(compilation, out var output, out var diagnostics); @@ -525,7 +526,7 @@ CSharpCompilation Create(string name, string source, params MetadataReference[] CSharpCompilation Generate(CSharpCompilation input) { var driver = CSharpGeneratorDriver.Create( - [new Type().AsSourceGenerator(), new Module().AsSourceGenerator()], + [new Type().AsSourceGenerator(), new Module().AsSourceGenerator(), new EnvironmentGenerator().AsSourceGenerator()], parseOptions: fixture.ParseOptions ); driver.RunGeneratorsAndUpdateCompilation(input, out var output, out var diagnostics); @@ -687,7 +688,7 @@ public static async Task NamespaceDescriptorCrossAssemblyRegistration() { var fixture = await Fixture.Compile("server", "net10.0"); var compilation = fixture.SampleCompilation; - foreach (var generator in new IIncrementalGenerator[] { new Type(), new Module() }) + foreach (var generator in new IIncrementalGenerator[] { new Type(), new Module(), new EnvironmentGenerator() }) { compilation = compilation.AddSyntaxTrees( fixture.RunGeneratorAndGetResult(generator).GeneratedTrees @@ -789,6 +790,11 @@ public static string[] ReducerNames(ModuleBuilder builder) => .SelectMany(section => section.Reducers_) .Select(reducer => reducer.SourceName).ToArray(); + public static string[] EnvironmentNames(ModuleBuilder builder) => + Describe(builder).Sections.OfType() + .SelectMany(section => section.Environment_) + .Select(declaration => declaration.Name).ToArray(); + public static bool CheckNamespaces() { const string first = "Library, Version=1.0.0.0"; @@ -881,6 +887,9 @@ byte[] Snapshot(object builder) => (byte[])consumerType.GetMethod("Snapshot")! var rootBefore = Snapshot(root); register.Invoke(null, [first]); + Assert.Equal(["REQUIRED", "OPTIONAL", "MODE"], (string[])consumerType.GetMethod("EnvironmentNames")! + .Invoke(null, [first])!); + Assert.Empty((string[])consumerType.GetMethod("EnvironmentNames")!.Invoke(null, [root])!); Assert.Contains("PublicTable", (string[])consumerType.GetMethod("TableNames")! .Invoke(null, [first])!); Assert.Contains("InsertData", (string[])consumerType.GetMethod("ReducerNames")! @@ -903,6 +912,69 @@ byte[] Snapshot(object builder) => (byte[])consumerType.GetMethod("Snapshot")! } } + [Fact] + public static async Task NamespaceEnvironmentAccessorsAreAssemblyLocal() + { + var fixture = await Fixture.Compile("server", "net10.0"); + const string usings = "global using System; global using System.IO; " + + "global using System.Linq; global using System.Collections.Generic;\n#pragma warning disable STDB_UNSTABLE\n"; + CSharpCompilation Generate(string name, string source, params MetadataReference[] references) + { + var input = CSharpCompilation.Create(name, + [CSharpSyntaxTree.ParseText(usings + source, fixture.ParseOptions)], + fixture.SampleCompilation.References.Concat(references), + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, + nullableContextOptions: NullableContextOptions.Enable)); + var driver = CSharpGeneratorDriver.Create( + [new Type().AsSourceGenerator(), new Module().AsSourceGenerator(), new EnvironmentGenerator().AsSourceGenerator()], + parseOptions: fixture.ParseOptions); + driver.RunGeneratorsAndUpdateCompilation(input, out var output, out var diagnostics); + Assert.Empty(diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error)); + Assert.Empty(GetCompilationErrors(output)); + Assert.DoesNotContain(output.GetDiagnostics(), d => d.Id is "CS0433" or "CS0436"); + return (CSharpCompilation)output; + } + MetadataReference Emit(CSharpCompilation compilation) + { + using var dll = new MemoryStream(); + var result = compilation.Emit(dll); + Assert.True(result.Success, string.Join("\n", result.Diagnostics)); + return MetadataReference.CreateFromImage(dll.ToArray()); + } + + var contexts = new[] { "ReducerContext", "ProcedureContext", "ProcedureTxContext", + "HandlerContext", "HandlerTxContext", "ViewContext", "AnonymousViewContext" }; + var library = Generate("EnvironmentLibrary", """ + [SpacetimeDB.Env] public struct LibrarySchema { public string? SHARED; public string? LIBRARY_ONLY; } + public static class LibraryHelpers { + public static string? Read(SpacetimeDB.ReducerContext ctx) => ctx.Env.SHARED; + } + """); + // An environment-only assembly must have a descriptor so it cannot disappear from discovery. + Assert.Single(library.GetSymbolsWithName("AssemblyDescriptor", SymbolFilter.Type)); + var dependency = Emit(library); + var root = Generate("EnvironmentRoot", """ + [SpacetimeDB.Env] public struct RootSchema { public string SHARED; public string? @class; } + public static class RootHelpers { + public static string? Library(SpacetimeDB.ReducerContext ctx) => LibraryHelpers.Read(ctx); + } + """ + string.Join("\n", contexts.Select((context, index) => $$""" + public static class Context{{index}} { + public static string Read(SpacetimeDB.{{context}} ctx) => ctx.Env.SHARED; + public static string? Keyword(SpacetimeDB.{{context}} ctx) => ctx.Env.@class; + public static string? Generic(SpacetimeDB.{{context}} ctx) => ctx.Env.Get("LIBRARY_ONLY"); + } + """)), dependency); + Emit(root); + var invalid = root.AddSyntaxTrees(CSharpSyntaxTree.ParseText(""" + public static class Invalid { + public static string? Read(SpacetimeDB.ReducerContext ctx) => ctx.Env.LIBRARY_ONLY; + } + """, fixture.ParseOptions)); + Assert.Contains(GetCompilationErrors(invalid), d => d.Id == "CS1061"); + Assert.DoesNotContain(root.SyntaxTrees, tree => tree.ToString().Contains("ModuleInitializer")); + } + [Fact] // Can a separately compiled DLL accept our module’s contexts, and can module code still access tables through the contexts it returns? public static async Task NamespaceContextsCrossAssemblyBoundaries() @@ -930,7 +1002,7 @@ public static async Task NamespaceContextsCrossAssemblyBoundaries() var compilation = fixture.SampleCompilation.AddReferences( MetadataReference.CreateFromImage(dll.ToArray()) ); - foreach (var generator in new IIncrementalGenerator[] { new Type(), new Module() }) + foreach (var generator in new IIncrementalGenerator[] { new Type(), new Module(), new EnvironmentGenerator() }) { compilation = compilation.AddSyntaxTrees( fixture.RunGeneratorAndGetResult(generator).GeneratedTrees @@ -974,6 +1046,8 @@ public static class InvalidViewWrites public static async Task TypeAndModuleGeneratorsOnServer() { var fixture = await Fixture.Compile("server"); + await fixture.Verify(nameof(EnvironmentGenerator), + fixture.RunGeneratorAndGetResult(new EnvironmentGenerator())); var compilationAfterGen = await fixture.RunAndCheckGenerators( new SpacetimeDB.Codegen.Type(), diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt index 63a906deab3..6add032f140 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt @@ -350,7 +350,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(793)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(983)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(800)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(990)]', Severity: Error, Descriptor: { Id: CS0121, @@ -373,7 +373,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(793)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(983)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(800)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(990)]', Severity: Error, Descriptor: { Id: CS0121, @@ -396,7 +396,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(773)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(963)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(780)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(970)]', Severity: Error, Descriptor: { Id: CS0121, @@ -419,7 +419,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(773)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(963)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(780)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(970)]', Severity: Error, Descriptor: { Id: CS0121, @@ -442,7 +442,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(783)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(973)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(790)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(980)]', Severity: Error, Descriptor: { Id: CS0121, @@ -465,7 +465,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(783)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(973)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(790)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(980)]', Severity: Error, Descriptor: { Id: CS0121, diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs index c12c30f82aa..cbce59ed659 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs @@ -659,6 +659,7 @@ public static class Handlers { } #if !NET10_0_OR_GREATER public sealed record ReducerContext : DbContext, Internal.IReducerContext { + public global::SpacetimeDB.ModuleEnvironment Env => default; public readonly Identity Sender; public readonly ConnectionId? ConnectionId; public readonly Random Rng; @@ -741,6 +742,7 @@ public Uuid NewUuidV7() public sealed partial class ProcedureContext : global::SpacetimeDB.ProcedureContextBase { + public new global::SpacetimeDB.ModuleEnvironment Env => default; private readonly Local _db = new(); internal ProcedureContext( @@ -819,6 +821,7 @@ public Uuid NewUuidV7() public sealed partial class HandlerContext : global::SpacetimeDB.HandlerContextBase { + public new global::SpacetimeDB.ModuleEnvironment Env => default; private readonly Local _db = new(); internal HandlerContext(Random random, Timestamp time) @@ -859,6 +862,8 @@ public Uuid NewUuidV7() public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase { + public new global::SpacetimeDB.ModuleEnvironment Env => default; + internal ProcedureTxContext(Internal.TxContext inner) : base(inner) { } @@ -868,6 +873,8 @@ internal ProcedureTxContext(Internal.TxContext inner) [Experimental("STDB_UNSTABLE")] public sealed class HandlerTxContext : global::SpacetimeDB.HandlerTxContextBase { + public new global::SpacetimeDB.ModuleEnvironment Env => default; + internal HandlerTxContext(Internal.TxContext inner) : base(inner) { } @@ -904,6 +911,7 @@ public sealed record ViewContext : DbContext, Internal.I { public Identity Sender { get; } + public global::SpacetimeDB.ModuleEnvironment Env => default; public QueryBuilder From => default; internal ViewContext(Identity sender, Internal.LocalReadOnly db) @@ -917,6 +925,7 @@ public sealed record AnonymousViewContext : DbContext, Internal.IAnonymousViewContext { + public global::SpacetimeDB.ModuleEnvironment Env => default; public QueryBuilder From => default; internal AnonymousViewContext(Internal.LocalReadOnly db) diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs index 771d8daf951..7647b610817 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs @@ -61,6 +61,7 @@ public static class Handlers { } #if !NET10_0_OR_GREATER public sealed record ReducerContext : DbContext, Internal.IReducerContext { + public global::SpacetimeDB.ModuleEnvironment Env => default; public readonly Identity Sender; public readonly ConnectionId? ConnectionId; public readonly Random Rng; @@ -143,6 +144,7 @@ public Uuid NewUuidV7() public sealed partial class ProcedureContext : global::SpacetimeDB.ProcedureContextBase { + public new global::SpacetimeDB.ModuleEnvironment Env => default; private readonly Local _db = new(); internal ProcedureContext( @@ -221,6 +223,7 @@ public Uuid NewUuidV7() public sealed partial class HandlerContext : global::SpacetimeDB.HandlerContextBase { + public new global::SpacetimeDB.ModuleEnvironment Env => default; private readonly Local _db = new(); internal HandlerContext(Random random, Timestamp time) @@ -261,6 +264,8 @@ public Uuid NewUuidV7() public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase { + public new global::SpacetimeDB.ModuleEnvironment Env => default; + internal ProcedureTxContext(Internal.TxContext inner) : base(inner) { } @@ -270,6 +275,8 @@ internal ProcedureTxContext(Internal.TxContext inner) [Experimental("STDB_UNSTABLE")] public sealed class HandlerTxContext : global::SpacetimeDB.HandlerTxContextBase { + public new global::SpacetimeDB.ModuleEnvironment Env => default; + internal HandlerTxContext(Internal.TxContext inner) : base(inner) { } @@ -286,6 +293,7 @@ public sealed record ViewContext : DbContext, Internal.I { public Identity Sender { get; } + public global::SpacetimeDB.ModuleEnvironment Env => default; public QueryBuilder From => default; internal ViewContext(Identity sender, Internal.LocalReadOnly db) @@ -299,6 +307,7 @@ public sealed record AnonymousViewContext : DbContext, Internal.IAnonymousViewContext { + public global::SpacetimeDB.ModuleEnvironment Env => default; public QueryBuilder From => default; internal AnonymousViewContext(Internal.LocalReadOnly db) diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/Lib.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/Lib.cs index 0a7ba3693eb..ff2673215e0 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/Lib.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/Lib.cs @@ -4,6 +4,15 @@ #pragma warning disable CA1050 // Declare types in namespaces - this is a test fixture, no need for a namespace. #pragma warning disable STDB_UNSTABLE // Enable experimental SpacetimeDB features +[SpacetimeDB.Env] +public struct EnvironmentSchema +{ + public string REQUIRED; + public string? OPTIONAL; + [SpacetimeDB.EnvValues("dev", "prod")] + public string MODE; +} + [SpacetimeDB.Type] public partial struct CustomStruct { diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/EnvironmentGenerator#Environment.g.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/EnvironmentGenerator#Environment.g.verified.cs new file mode 100644 index 00000000000..43a64d42e94 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/EnvironmentGenerator#Environment.g.verified.cs @@ -0,0 +1,46 @@ +//HintName: Environment.g.cs +// +#nullable enable +#pragma warning disable CS0436 +namespace SpacetimeDB +{ + public readonly struct ModuleEnvironment + { + public string? Get(string key) => default(global::SpacetimeDB.DatabaseEnvironment).Get(key); + + public string @REQUIRED => + Get("REQUIRED") + ?? throw new global::System.InvalidOperationException( + "Required environment value is absent" + ); + public string? @OPTIONAL => Get("OPTIONAL"); + public string @MODE => + Get("MODE") + ?? throw new global::System.InvalidOperationException( + "Required environment value is absent" + ); + } + + internal static class EnvironmentRegistration + { + [global::System.Runtime.CompilerServices.ModuleInitializer] + internal static void Register() + { + global::SpacetimeDB.Internal.Module.RegisterEnvironment( + new("REQUIRED", new global::SpacetimeDB.Internal.EnvVarType.String(default), false) + ); + global::SpacetimeDB.Internal.Module.RegisterEnvironment( + new("OPTIONAL", new global::SpacetimeDB.Internal.EnvVarType.String(default), true) + ); + global::SpacetimeDB.Internal.Module.RegisterEnvironment( + new( + "MODE", + new global::SpacetimeDB.Internal.EnvVarType.Union( + new global::System.Collections.Generic.List { "dev", "prod" } + ), + false + ) + ); + } + } +} diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/EnvironmentGenerator.net10#Environment.g.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/EnvironmentGenerator.net10#Environment.g.verified.cs new file mode 100644 index 00000000000..eeb542f1cb9 --- /dev/null +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/EnvironmentGenerator.net10#Environment.g.verified.cs @@ -0,0 +1,23 @@ +//HintName: Environment.g.cs +// +#nullable enable +namespace SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +{ + public static class EnvironmentExtensions + { + extension(global::SpacetimeDB.DatabaseEnvironment env) + { + public string @REQUIRED => + env.Get("REQUIRED") + ?? throw new global::System.InvalidOperationException( + "Required environment value is absent" + ); + public string? @OPTIONAL => env.Get("OPTIONAL"); + public string @MODE => + env.Get("MODE") + ?? throw new global::System.InvalidOperationException( + "Required environment value is absent" + ); + } + } +} diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs index dac447a1ebc..34cd7c912be 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs @@ -503,6 +503,7 @@ public static class Handlers { } #if !NET10_0_OR_GREATER public sealed record ReducerContext : DbContext, Internal.IReducerContext { + public global::SpacetimeDB.ModuleEnvironment Env => default; public readonly Identity Sender; public readonly ConnectionId? ConnectionId; public readonly Random Rng; @@ -585,6 +586,7 @@ public Uuid NewUuidV7() public sealed partial class ProcedureContext : global::SpacetimeDB.ProcedureContextBase { + public new global::SpacetimeDB.ModuleEnvironment Env => default; private readonly Local _db = new(); internal ProcedureContext( @@ -663,6 +665,7 @@ public Uuid NewUuidV7() public sealed partial class HandlerContext : global::SpacetimeDB.HandlerContextBase { + public new global::SpacetimeDB.ModuleEnvironment Env => default; private readonly Local _db = new(); internal HandlerContext(Random random, Timestamp time) @@ -703,6 +706,8 @@ public Uuid NewUuidV7() public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase { + public new global::SpacetimeDB.ModuleEnvironment Env => default; + internal ProcedureTxContext(Internal.TxContext inner) : base(inner) { } @@ -712,6 +717,8 @@ internal ProcedureTxContext(Internal.TxContext inner) [Experimental("STDB_UNSTABLE")] public sealed class HandlerTxContext : global::SpacetimeDB.HandlerTxContextBase { + public new global::SpacetimeDB.ModuleEnvironment Env => default; + internal HandlerTxContext(Internal.TxContext inner) : base(inner) { } @@ -742,6 +749,7 @@ public sealed record ViewContext : DbContext, Internal.I { public Identity Sender { get; } + public global::SpacetimeDB.ModuleEnvironment Env => default; public QueryBuilder From => default; internal ViewContext(Identity sender, Internal.LocalReadOnly db) @@ -755,6 +763,7 @@ public sealed record AnonymousViewContext : DbContext, Internal.IAnonymousViewContext { + public global::SpacetimeDB.ModuleEnvironment Env => default; public QueryBuilder From => default; internal AnonymousViewContext(Internal.LocalReadOnly db) @@ -3620,7 +3629,21 @@ internal static void Register( { // HTTP routes retain the root routing API even for mounted modules. httpBuilder ??= builder; - + builder.RegisterEnvironment( + new("REQUIRED", new global::SpacetimeDB.Internal.EnvVarType.String(default), false) + ); + builder.RegisterEnvironment( + new("OPTIONAL", new global::SpacetimeDB.Internal.EnvVarType.String(default), true) + ); + builder.RegisterEnvironment( + new( + "MODE", + new global::SpacetimeDB.Internal.EnvVarType.Union( + new global::System.Collections.Generic.List { "dev", "prod" } + ), + false + ) + ); var __memoryStream = new MemoryStream(); var __writer = new BinaryWriter(__memoryStream); diff --git a/crates/bindings-csharp/Codegen/Environment.cs b/crates/bindings-csharp/Codegen/Environment.cs index 5162abfe8e7..92f75ba8500 100644 --- a/crates/bindings-csharp/Codegen/Environment.cs +++ b/crates/bindings-csharp/Codegen/Environment.cs @@ -25,25 +25,41 @@ public sealed class EnvironmentGenerator : IIncrementalGenerator public void Initialize(IncrementalGeneratorInitializationContext context) { - var declarations = context + var declarations = Declarations(context); + var assembly = context.CompilationProvider.Select( + (compilation, _) => + ( + SharedContexts: Module.UsesSharedContexts(compilation), + Namespace: Module.AssemblyNamespace(compilation.Assembly) + ) + ); + context.RegisterSourceOutput( + declarations.Combine(assembly), + (ctx, input) => + Generate(ctx, input.Left, input.Right.SharedContexts, input.Right.Namespace) + ); + } + + internal static IncrementalValueProvider> Declarations( + IncrementalGeneratorInitializationContext context + ) => + context .SyntaxProvider.ForAttributeWithMetadataName( "SpacetimeDB.EnvAttribute", (_, _) => true, (ctx, _) => (INamedTypeSymbol)ctx.TargetSymbol ) .Collect(); - context.RegisterSourceOutput(declarations, Generate); - } - private static void Generate( - SourceProductionContext context, - ImmutableArray types + internal static string RegistrationCode(ImmutableArray types) => + string.Join("\n", Parse(types, true, (_, _) => { }).Registrations); + + private static (List Properties, List Registrations) Parse( + ImmutableArray types, + bool sharedContexts, + Action Report ) { - void Report(ISymbol symbol, string message) => - context.ReportDiagnostic( - Diagnostic.Create(InvalidDeclaration, symbol.Locations.FirstOrDefault(), message) - ); if (types.Length > 1) { foreach (var type in types) @@ -119,7 +135,7 @@ void Report(ISymbol symbol, string message) => : $"new global::SpacetimeDB.Internal.EnvVarType.Union(new global::System.Collections.Generic.List {{ {string.Join(", ", strings.Select(Literal))} }})"; } registrations.Add( - $"global::SpacetimeDB.Internal.Module.RegisterEnvironment(new({Literal(name)}, {constraint}, {(optional ? "true" : "false")}));" + $"{(sharedContexts ? "builder" : "global::SpacetimeDB.Internal.Module")}.RegisterEnvironment(new({Literal(name)}, {constraint}, {(optional ? "true" : "false")}));" ); // Preserve the checked generic method, including a key literally // named Get, and inherited object members. Keywords are escaped @@ -136,12 +152,52 @@ void Report(ISymbol symbol, string message) => or "MemberwiseClone" ) continue; - var read = $"Get({Literal(name)})"; + var read = $"{(sharedContexts ? "env." : "")}Get({Literal(name)})"; if (!optional) read += " ?? throw new global::System.InvalidOperationException(\"Required environment value is absent\")"; properties.Add($"public string{(optional ? "?" : "")} @{name} => {read};"); } + return (properties, registrations); + } + + private static void Generate( + SourceProductionContext context, + ImmutableArray types, + bool sharedContexts, + string assemblyNamespace + ) + { + var (properties, registrations) = Parse( + types, + sharedContexts, + (symbol, message) => + context.ReportDiagnostic( + Diagnostic.Create( + InvalidDeclaration, + symbol.Locations.FirstOrDefault(), + message + ) + ) + ); + if (sharedContexts) + { + context.AddSource( + "Environment.g.cs", + $$""" + // + #nullable enable + namespace {{assemblyNamespace}} { + public static class EnvironmentExtensions { + extension(global::SpacetimeDB.DatabaseEnvironment env) { + {{string.Join("\n", properties)}} + } + } + } + """ + ); + return; + } context.AddSource( "Environment.g.cs", $$""" diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index daf8e89b0e2..4a0ac4b7d23 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -2585,13 +2585,23 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Combine(columnDefaultValues) .Select((tuple, ct) => FlattenModuleOutputInputs(tuple)); + var environment = EnvironmentGenerator.Declarations(context).Select((types, _) => ( + HasDeclarations: types.Length != 0, + Registrations: EnvironmentGenerator.RegistrationCode(types) + )); var extensionNamespace = context.CompilationProvider.Select( (compilation, _) => ( Name: AssemblyNamespace(compilation.Assembly), Identity: compilation.Assembly.Identity.ToString(), SharedContexts: UsesSharedContexts(compilation) ) - ); + ).Combine(environment).Select((input, _) => ( + input.Left.Name, + input.Left.Identity, + input.Left.SharedContexts, + HasEnvironment: input.Right.HasDeclarations, + EnvironmentRegistrations: input.Right.Registrations + )); var referencedAssemblies = context.CompilationProvider.Select(DiscoverAssemblies); var namespaceDeclarations = context.CompilationProvider @@ -2618,9 +2628,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Combine(namespaceDeclarations), (context, input) => { - var (((inputs, assemblyContext), assemblies), mounts) = input; - var extensionNamespaceName = assemblyContext.Name; - var handlesNamespace = assemblyContext.SharedContexts + var (((inputs, (extensionNamespaceName, identity, sharedContexts, hasEnvironment, environmentRegistrations)), assemblies), mounts) = input; + var handlesNamespace = sharedContexts ? extensionNamespaceName : "SpacetimeDB.Internal"; var mountByIdentity = mounts.SelectMany(m => m) .ToDictionary(m => m.AssemblyIdentity, StringComparer.Ordinal); @@ -2669,7 +2678,7 @@ string ConsumerAccessors(string container) var members = new List(); var used = new Dictionary(StringComparer.Ordinal); foreach (var table in tableAccessors) - used[table.TableAccessorName] = assemblyContext.Identity; + used[table.TableAccessorName] = identity; void Add(string name, string owner, string declaration) { if (used.TryGetValue(name, out var previous)) @@ -2712,7 +2721,7 @@ void Add(string name, string owner, string declaration) var compositionRegistration = new List { "global::SpacetimeDB.Internal.Module.InstallNamespaces(new global::SpacetimeDB.Internal.NamespaceRegistry(" - + SymbolDisplay.FormatLiteral(assemblyContext.Identity, true) + ", new global::System.Collections.Generic.KeyValuePair[] {" + + SymbolDisplay.FormatLiteral(identity, true) + ", new global::System.Collections.Generic.KeyValuePair[] {" + string.Join(",", mountByIdentity.Values.Select(m => $"new({SymbolDisplay.FormatLiteral(m.AssemblyIdentity, true)}, {SymbolDisplay.FormatLiteral(m.Accessor, true)})")) + "}));", $"global::{extensionNamespaceName}.AssemblyDescriptor.Register(global::SpacetimeDB.Internal.Module.RootBuilder);" @@ -2799,6 +2808,7 @@ void Add(string name, string owner, string declaration) var preRegistrationLines = new[] { + sharedContexts ? environmentRegistrations : "", settingsRegistration, explicitTableRegistrations, explicitFunctionRegistrations, @@ -2829,6 +2839,7 @@ void Add(string name, string owner, string declaration) && addHttpHandlers.Array.IsEmpty && views.Array.IsEmpty && assemblies.Array.IsEmpty + && !hasEnvironment ) { return; diff --git a/crates/bindings-csharp/README.md b/crates/bindings-csharp/README.md index 947f57c9a08..764683928b7 100644 --- a/crates/bindings-csharp/README.md +++ b/crates/bindings-csharp/README.md @@ -47,3 +47,10 @@ allow no environment keys. Undeclared reads and reads from host-dispatched submodules fail at runtime. Values are private, durable database configuration for secrets and other settings. Database owners and authorized collaborators can read them; module code can expose them through its own outputs. + +Environment declarations register through each assembly's descriptor on .NET 10. +Dependencies automatically registered in `public` contribute to the root schema; +mounted dependencies cannot declare environment variables (the host rejects them). +A library helper invoked by root code can use `ctx.Env.Get("KEY")` for a root-declared +key. Calling that library through a namespaced host entrypoint does not grant +environment access, even for a key declared by the root. diff --git a/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs b/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs index cf172d9dedf..7a6dd4c3c40 100644 --- a/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs +++ b/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs @@ -200,7 +200,7 @@ internal void RegisterView(RawViewDefV10 view) viewDefs.Add(view); } - internal void RegisterEnvironment(EnvironmentDeclaration declaration) => + public void RegisterEnvironment(EnvironmentDeclaration declaration) => environment.Add(declaration); public void RegisterViewPrimaryKey(string viewSourceName, IEnumerable columns) => diff --git a/crates/bindings-csharp/Runtime/ModuleContexts.cs b/crates/bindings-csharp/Runtime/ModuleContexts.cs index 1578461c38a..8bbde15ab77 100644 --- a/crates/bindings-csharp/Runtime/ModuleContexts.cs +++ b/crates/bindings-csharp/Runtime/ModuleContexts.cs @@ -9,6 +9,7 @@ namespace SpacetimeDB; public sealed class Local : LocalBase { } public sealed record ReducerContext : DbContext, Internal.IReducerContext { + public DatabaseEnvironment Env => default; public readonly Identity Sender; public readonly ConnectionId? ConnectionId; public readonly Random Rng; @@ -203,6 +204,7 @@ internal HandlerTxContext(Internal.TxContext inner) : base(inner) {} public sealed record ViewContext : DbContext, Internal.IViewContext { + public DatabaseEnvironment Env => default; public Identity Sender { get; } public QueryBuilder From => default; @@ -216,6 +218,7 @@ internal ViewContext(Identity sender, Internal.LocalReadOnly db) public sealed record AnonymousViewContext : DbContext, Internal.IAnonymousViewContext { + public DatabaseEnvironment Env => default; public QueryBuilder From => default; internal AnonymousViewContext(Internal.LocalReadOnly db) diff --git a/crates/testing/tests/standalone_integration_test.rs b/crates/testing/tests/standalone_integration_test.rs index 0ffe309d9ac..2ffccce1790 100644 --- a/crates/testing/tests/standalone_integration_test.rs +++ b/crates/testing/tests/standalone_integration_test.rs @@ -137,6 +137,15 @@ fn namespace_csharp_mounted_dependencies() { CompiledModule::compile("namespace-test-cs", CompilationMode::Debug).with_module_async( DEFAULT_CONFIG, |mut module| async move { + // Library helpers inherit a root call's environment access; host-dispatched children do not. + assert_eq!( + module.call_procedure_with_args("read_environment", "[]").await.unwrap(), + AlgebraicValue::String("unset".into()) + ); + assert!(module + .call_procedure_with_args("MyAuth.read_environment", "[]") + .await + .is_err()); // Extra is discovered without any application reference to its helpers. module.call_reducer_binary("extra", &product![]).await.unwrap(); module.call_reducer_binary("exercise", &product![]).await.unwrap(); diff --git a/modules/namespace-test-cs/Lib.cs b/modules/namespace-test-cs/Lib.cs index d42e6c75b0b..3ae12660e43 100644 --- a/modules/namespace-test-cs/Lib.cs +++ b/modules/namespace-test-cs/Lib.cs @@ -5,6 +5,12 @@ namespace NamespaceRoot; +[SpacetimeDB.Env] +public struct EnvironmentSchema +{ + public string? NAMESPACE_TEST; +} + [Table(Accessor = "User", Public = true)] public partial struct User { @@ -71,6 +77,20 @@ public static void Exercise(ReducerContext ctx) public static ulong CountUsers(ProcedureContext ctx) => ctx.WithTx(tx => tx.Db.User.Count + tx.Db.MyAuth.User.Count + tx.Db.@class.User.Count); + [Procedure] + public static string ReadEnvironment(ProcedureContext ctx) + { + var value = ctx.Env.NAMESPACE_TEST; + if (AuthLib.Functions.ReadEnvironment(ctx) != (value ?? "unset")) + throw new Exception("Library helper must read the root invocation's environment"); + return ctx.WithTx(tx => + { + if (tx.Env.NAMESPACE_TEST != value) + throw new Exception("Transaction environment differs from procedure environment"); + return value ?? "unset"; + }); + } + [Procedure] public static uint WriteAcrossNamespaces(ProcedureContext ctx, uint id, bool fail) => ctx.WithTx(tx => diff --git a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs index a530c749c32..93922014531 100644 --- a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs +++ b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs @@ -85,6 +85,10 @@ public static uint ReadScore(ProcedureContext ctx, uint id) => [Procedure] public static ulong CountUsers(ProcedureContext ctx) => ctx.WithTx(tx => tx.Db.User.Count); + [Procedure] + public static string ReadEnvironment(ProcedureContext ctx) => + ctx.Env.Get("NAMESPACE_TEST") ?? "unset"; + [View(Accessor = "Users", Public = true)] public static User? Users(ViewContext ctx) => ctx.Db.User.Id.Find(2); diff --git a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs index 75d82fbf800..dcc0fa8fb51 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs @@ -252,7 +252,21 @@ void EmptyCache() procedures++; } ); - Wait(() => procedures == 5, "namespaced procedure callbacks"); + conn.Procedures.ReadEnvironment( + (_, result) => + { + Require(result.IsSuccess && result.Value == "unset", "Root environment access"); + procedures++; + } + ); + conn.Procedures.MyAuth.ReadEnvironment( + (_, result) => + { + Require(!result.IsSuccess, "Namespaced calls must not read the root environment"); + procedures++; + } + ); + Wait(() => procedures == 7, "namespaced procedure callbacks"); var updated = false; conn.Db.MyAuth.User.OnUpdate += (ctx, before, after) => diff --git a/sdks/csharp/examples~/regression-tests/namespaces/README.md b/sdks/csharp/examples~/regression-tests/namespaces/README.md index ee18dc0e757..7bffbbaf1f3 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/README.md +++ b/sdks/csharp/examples~/regression-tests/namespaces/README.md @@ -34,6 +34,8 @@ Coverage: atomic subscription callbacks, and persisted results through one-off queries. - Same-named reducers/procedures in different namespaces, procedure success/error callbacks, and child reducer failures forwarded to the root connection. +- Root environment reads through typed accessors, a library helper and a procedure + transaction; rejection of environment reads in host-dispatched namespace procedures. - Insert/update/delete callbacks, unique/B-tree indexes, and reducer rollback. - Event rows, private-table access rejection, procedural/anonymous/query views. - Root-defined RLS on a public namespaced table: two distinct non-owner clients, diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadEnvironment.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadEnvironment.g.cs new file mode 100644 index 00000000000..6667f82ff60 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadEnvironment.g.cs @@ -0,0 +1,65 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types.@MyAuth +{ + public sealed partial class RemoteProcedures : RemoteBase + { + public void ReadEnvironment(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalReadEnvironment((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalReadEnvironment(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.ReadEnvironmentArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ReadEnvironment + { + [DataMember(Name = "Value")] + public string Value; + + public ReadEnvironment(string Value) + { + this.Value = Value; + } + + public ReadEnvironment() + { + this.Value = ""; + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ReadEnvironmentArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "MyAuth.read_environment"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/ReadEnvironment.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/ReadEnvironment.g.cs new file mode 100644 index 00000000000..e7c19213dd4 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/ReadEnvironment.g.cs @@ -0,0 +1,65 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteProcedures : RemoteBase + { + public void ReadEnvironment(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalReadEnvironment((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalReadEnvironment(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.ReadEnvironmentArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ReadEnvironment + { + [DataMember(Name = "Value")] + public string Value; + + public ReadEnvironment(string Value) + { + this.Value = Value; + } + + public ReadEnvironment() + { + this.Value = ""; + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ReadEnvironmentArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "read_environment"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs index 9fd4f2dd7bd..2933600fd49 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.10.1 (commit 27792e4855011d77014872795ead58a9b0c894e8). +// This was generated using spacetimedb cli version 2.10.1 (commit fc03797a117b64e157e2bc7e35628c7ac960aa18). #nullable enable From 24c35c0888d7910b06922269549711012917ccac Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Mon, 21 Sep 2026 11:57:27 -0500 Subject: [PATCH 17/49] Clean GenerateQueryBuilderMembers --- crates/bindings-csharp/Codegen/Module.cs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 4a0ac4b7d23..3a6ceee0d86 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -925,6 +925,7 @@ public IEnumerable GenerateReadOnlyAccessors() } } + // useExtensions means we're in a .NET 10 context public IEnumerable GenerateQueryBuilderMembers(bool useExtensions = false) { if (Kind is TypeKind.Sum) @@ -947,8 +948,7 @@ string ColDecl(ColumnDeclaration col) var typeName = col.Type.Name; var isNullable = typeName.EndsWith("?", StringComparison.Ordinal); var valueTypeName = isNullable ? typeName[..^1] : typeName; - var colType = isNullable ? "global::SpacetimeDB.Col" : "global::SpacetimeDB.Col"; - return $"public readonly {colType}<{globalRowName}, {valueTypeName}> {col.Identifier};"; + return $"public readonly global::SpacetimeDB.Col<{globalRowName}, {valueTypeName}> {col.Identifier};"; } string ColInit(ColumnDeclaration col) @@ -956,14 +956,13 @@ string ColInit(ColumnDeclaration col) var typeName = col.Type.Name; var isNullable = typeName.EndsWith("?", StringComparison.Ordinal); var valueTypeName = isNullable ? typeName[..^1] : typeName; - var colType = isNullable ? "global::SpacetimeDB.Col" : "global::SpacetimeDB.Col"; - return $"{col.Identifier} = new {colType}<{globalRowName}, {valueTypeName}>(tableName, \"{col.Name}\");"; + return $"{col.Identifier} = new global::SpacetimeDB.Col<{globalRowName}, {valueTypeName}>(tableName, \"{col.Name}\");"; } var colsDecls = string.Join("\n ", Members.Select(ColDecl)); var colsInits = string.Join("\n ", Members.Select(ColInit)); - var ixPositions = new global::System.Collections.Generic.HashSet(); + var ixPositions = new HashSet(); foreach (var c in GetConstraints(accessor, ColumnAttrs.PrimaryKey | ColumnAttrs.Unique)) { ixPositions.Add(c.Pos); @@ -988,10 +987,7 @@ string IxColDecl(ColumnDeclaration col) var typeName = col.Type.Name; var isNullable = typeName.EndsWith("?", StringComparison.Ordinal); var valueTypeName = isNullable ? typeName[..^1] : typeName; - var colType = isNullable - ? "global::SpacetimeDB.IxCol" - : "global::SpacetimeDB.IxCol"; - return $"public readonly {colType}<{globalRowName}, {valueTypeName}> {col.Identifier};"; + return $"public readonly global::SpacetimeDB.IxCol<{globalRowName}, {valueTypeName}> {col.Identifier};"; } string IxColInit(ColumnDeclaration col) @@ -999,10 +995,7 @@ string IxColInit(ColumnDeclaration col) var typeName = col.Type.Name; var isNullable = typeName.EndsWith("?", StringComparison.Ordinal); var valueTypeName = isNullable ? typeName[..^1] : typeName; - var colType = isNullable - ? "global::SpacetimeDB.IxCol" - : "global::SpacetimeDB.IxCol"; - return $"{col.Identifier} = new {colType}<{globalRowName}, {valueTypeName}>(tableName, \"{col.Name}\");"; + return $"{col.Identifier} = new global::SpacetimeDB.IxCol<{globalRowName}, {valueTypeName}>(tableName, \"{col.Name}\");"; } var ixColsDecls = string.Join("\n ", ixMembers.Select(IxColDecl)); @@ -1039,6 +1032,7 @@ public readonly partial struct QueryBuilder } """; + yield return $$""" {{vis}} readonly struct {{colsTypeName}} { From cbb91aa1d725e583bb208fc954a05d806df52d90 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Mon, 21 Sep 2026 12:10:44 -0500 Subject: [PATCH 18/49] Update namespace for dependencies --- crates/bindings-csharp/Codegen/Module.cs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 3a6ceee0d86..5621c6f7a8b 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -4,6 +4,7 @@ namespace SpacetimeDB.Codegen; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Text.RegularExpressions; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -2089,10 +2090,26 @@ public class Module : IIncrementalGenerator internal static bool UsesSharedContexts(Compilation compilation) => compilation.SyntaxTrees.Any(tree => tree.Options is CSharpParseOptions options && options.PreprocessorSymbolNames.Contains("NET10_0_OR_GREATER")); + + internal static string AssemblyNamespace(IAssemblySymbol assembly) + { + var name = Regex.Replace(assembly.Name, @"[^A-Za-z0-9_]", "_"); + + if (name.Length == 0 || char.IsDigit(name[0])) + { + name = "_" + name; + } - internal static string AssemblyNamespace(IAssemblySymbol assembly) => - "SpacetimeDB.Generated.Assembly_" - + string.Concat(assembly.Identity.ToString().Select(c => ((int)c).ToString("X4"))); + using var sha256 = System.Security.Cryptography.SHA256.Create(); + var hash = sha256.ComputeHash( + System.Text.Encoding.UTF8.GetBytes(assembly.Identity.ToString()) + ); + var suffix = string.Concat( + hash.Take(8).Select(b => b.ToString("X2")) + ); + + return $"SpacetimeDB.Generated.{name}_{suffix}"; + } private static string IndentGeneratedCode(string code, int spaces) => code.Replace("\n", "\n" + new string(' ', spaces)); From 3c80bfbb5f02743dd3c35fcb6dd214428d92de60 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Mon, 21 Sep 2026 12:34:31 -0500 Subject: [PATCH 19/49] Verify new namespaces --- .../ExtraCompilationErrors.net10.verified.txt | 16 +- .../diag/snapshots/Module#FFI.verified.cs | 51 ++-- .../snapshots/Module.net10#FFI.verified.cs | 221 +++++++++--------- .../snapshots/Module#FFI.verified.cs | 38 +-- .../snapshots/Module.net10#FFI.verified.cs | 58 ++--- ...tGenerator.net10#Environment.g.verified.cs | 2 +- .../server/snapshots/Module#FFI.verified.cs | 42 ++-- .../snapshots/Module.net10#FFI.verified.cs | 172 +++++++------- .../module_bindings/SpacetimeDBClient.g.cs | 2 +- .../module_bindings/SpacetimeDBClient.g.cs | 4 +- .../module_bindings/SpacetimeDBClient.g.cs | 2 +- .../module_bindings/SpacetimeDBClient.g.cs | 2 +- 12 files changed, 288 insertions(+), 322 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt index 6add032f140..faa165e7d56 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt @@ -350,7 +350,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(800)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(990)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(800)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(990)]', Severity: Error, Descriptor: { Id: CS0121, @@ -373,7 +373,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(800)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(990)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(800)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(990)]', Severity: Error, Descriptor: { Id: CS0121, @@ -396,7 +396,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(780)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(970)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(780)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(970)]', Severity: Error, Descriptor: { Id: CS0121, @@ -419,7 +419,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(780)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(970)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(780)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(970)]', Severity: Error, Descriptor: { Id: CS0121, @@ -442,7 +442,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(790)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(980)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(790)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(980)]', Severity: Error, Descriptor: { Id: CS0121, @@ -465,7 +465,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(790)]' and 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(980)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(790)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(980)]', Severity: Error, Descriptor: { Id: CS0121, @@ -488,7 +488,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^^^^^ { */ - Message: The namespace 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C' already contains a definition for 'TestDuplicateTableNameCols', + Message: The namespace 'SpacetimeDB.Generated.diag_4F830E2879BB50E3' already contains a definition for 'TestDuplicateTableNameCols', Severity: Error, Descriptor: { Id: CS0101, @@ -511,7 +511,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ { */ - Message: The namespace 'SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C' already contains a definition for 'TestDuplicateTableNameIxCols', + Message: The namespace 'SpacetimeDB.Generated.diag_4F830E2879BB50E3' already contains a definition for 'TestDuplicateTableNameIxCols', Severity: Error, Descriptor: { Id: CS0101, diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs index 1b4b09a8e2c..1d7b6d52807 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs @@ -6,7 +6,7 @@ #pragma warning disable STDB_UNSTABLE #if NET10_0_OR_GREATER -global using SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C; +global using SpacetimeDB.Generated.diag_4F830E2879BB50E3; #endif using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; @@ -15,7 +15,7 @@ using TxContext = SpacetimeDB.Internal.TxContext; #if NET10_0_OR_GREATER [assembly: global::SpacetimeDB.ModuleDescriptorAttribute( - typeof(global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor) + typeof(global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor) )] #endif @@ -933,7 +933,7 @@ internal AnonymousViewContext(Internal.LocalReadOnly db) } #if NET10_0_OR_GREATER -namespace SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +namespace SpacetimeDB.Generated.diag_4F830E2879BB50E3 { public static partial class AssemblyDescriptor { @@ -4581,7 +4581,7 @@ internal static void Initialize() new global::System.Collections.Generic.KeyValuePair[] { } ) ); - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Register( + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Register( global::SpacetimeDB.Internal.Module.RootBuilder ); #else @@ -5634,13 +5634,9 @@ SpacetimeDB.Internal.BytesSink error if ( (uint)localId < (uint) - global::SpacetimeDB - .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C - .AssemblyDescriptor - .ReducerCount + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.ReducerCount ) - return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalReducer( + return global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.CallLocalReducer( localId, sender_0, sender_1, @@ -5654,7 +5650,7 @@ SpacetimeDB.Internal.BytesSink error ); localId -= global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .ReducerCount; return SpacetimeDB.Internal.Module.WriteReducerError( @@ -5812,11 +5808,11 @@ SpacetimeDB.Internal.BytesSink result_sink < (uint) global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .ProcedureCount ) - return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalProcedure( + return global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.CallLocalProcedure( localId, sender_0, sender_1, @@ -5830,7 +5826,7 @@ SpacetimeDB.Internal.BytesSink result_sink ); localId -= global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .ProcedureCount; throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); @@ -5894,11 +5890,11 @@ SpacetimeDB.Internal.BytesSink response_body_sink < (uint) global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .HttpHandlerCount ) - return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalHttpHandler( + return global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.CallLocalHttpHandler( localId, timestamp, request, @@ -5908,7 +5904,7 @@ SpacetimeDB.Internal.BytesSink response_body_sink ); localId -= global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .HttpHandlerCount; throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); @@ -5962,14 +5958,9 @@ SpacetimeDB.Internal.BytesSink sink var localId = id; if ( (uint)localId - < (uint) - global::SpacetimeDB - .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C - .AssemblyDescriptor - .ViewCount + < (uint)global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.ViewCount ) - return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalView( + return global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.CallLocalView( localId, sender_0, sender_1, @@ -5978,11 +5969,7 @@ SpacetimeDB.Internal.BytesSink sink args, sink ); - localId -= global::SpacetimeDB - .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C - .AssemblyDescriptor - .ViewCount; + localId -= global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.ViewCount; return UnknownViewId(id); #else return CallLocalView(id, sender_0, sender_1, sender_2, sender_3, args, sink); @@ -6035,18 +6022,18 @@ SpacetimeDB.Internal.BytesSink sink < (uint) global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .AnonymousViewCount ) - return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalAnonymousView( + return global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.CallLocalAnonymousView( localId, args, sink ); localId -= global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .AnonymousViewCount; return UnknownAnonymousViewId(id); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs index cbce59ed659..c22232203c8 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs @@ -6,7 +6,7 @@ #pragma warning disable STDB_UNSTABLE #if NET10_0_OR_GREATER -global using SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C; +global using SpacetimeDB.Generated.diag_4F830E2879BB50E3; #endif using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; @@ -15,7 +15,7 @@ using TxContext = SpacetimeDB.Internal.TxContext; #if NET10_0_OR_GREATER [assembly: global::SpacetimeDB.ModuleDescriptorAttribute( - typeof(global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor) + typeof(global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor) )] #endif @@ -883,27 +883,27 @@ internal HandlerTxContext(Internal.TxContext inner) public sealed class Local : global::SpacetimeDB.LocalBase { - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.Player Player => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.Player Player => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestAutoIncNotInteger TestAutoIncNotInteger => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestAutoIncNotInteger TestAutoIncNotInteger => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDefaultFieldValues TestDefaultFieldValues => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestDefaultFieldValues TestDefaultFieldValues => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDuplicateTableName TestDuplicateTableName => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestDuplicateTableName TestDuplicateTableName => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestIndexIssues TestIndexIssues => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestIndexIssues TestIndexIssues => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithMissingScheduleAtField TestScheduleWithMissingScheduleAtField => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithMissingScheduleAtField TestScheduleWithMissingScheduleAtField => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutPrimaryKey TestScheduleWithoutPrimaryKey => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithoutPrimaryKey TestScheduleWithoutPrimaryKey => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutScheduleAt TestScheduleWithoutScheduleAt => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithoutScheduleAt TestScheduleWithoutScheduleAt => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongPrimaryKeyType TestScheduleWithWrongPrimaryKeyType => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithWrongPrimaryKeyType TestScheduleWithWrongPrimaryKeyType => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongScheduleAtType TestScheduleWithWrongScheduleAtType => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithWrongScheduleAtType TestScheduleWithWrongScheduleAtType => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestUniqueNotEquatable TestUniqueNotEquatable => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestUniqueNotEquatable TestUniqueNotEquatable => new(); } @@ -935,7 +935,7 @@ internal AnonymousViewContext(Internal.LocalReadOnly db) } #if NET10_0_OR_GREATER -namespace SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +namespace SpacetimeDB.Generated.diag_4F830E2879BB50E3 { public static partial class AssemblyDescriptor { @@ -1046,53 +1046,53 @@ public static void Register( public readonly struct Tables { - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.Player Player => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.Player Player => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestAutoIncNotInteger TestAutoIncNotInteger => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestAutoIncNotInteger TestAutoIncNotInteger => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDefaultFieldValues TestDefaultFieldValues => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestDefaultFieldValues TestDefaultFieldValues => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDuplicateTableName TestDuplicateTableName => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestDuplicateTableName TestDuplicateTableName => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestIndexIssues TestIndexIssues => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestIndexIssues TestIndexIssues => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithMissingScheduleAtField TestScheduleWithMissingScheduleAtField => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithMissingScheduleAtField TestScheduleWithMissingScheduleAtField => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutPrimaryKey TestScheduleWithoutPrimaryKey => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithoutPrimaryKey TestScheduleWithoutPrimaryKey => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutScheduleAt TestScheduleWithoutScheduleAt => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithoutScheduleAt TestScheduleWithoutScheduleAt => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongPrimaryKeyType TestScheduleWithWrongPrimaryKeyType => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithWrongPrimaryKeyType TestScheduleWithWrongPrimaryKeyType => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongScheduleAtType TestScheduleWithWrongScheduleAtType => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithWrongScheduleAtType TestScheduleWithWrongScheduleAtType => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestUniqueNotEquatable TestUniqueNotEquatable => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestUniqueNotEquatable TestUniqueNotEquatable => new(); } public readonly struct ReadOnlyTables { - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PlayerReadOnly Player => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.PlayerReadOnly Player => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestAutoIncNotIntegerReadOnly TestAutoIncNotInteger => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestAutoIncNotIntegerReadOnly TestAutoIncNotInteger => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestDefaultFieldValuesReadOnly TestDefaultFieldValues => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestDefaultFieldValuesReadOnly TestDefaultFieldValues => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestDuplicateTableNameReadOnly TestDuplicateTableName => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestDuplicateTableNameReadOnly TestDuplicateTableName => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestIndexIssuesReadOnly TestIndexIssues => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestIndexIssuesReadOnly TestIndexIssues => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithMissingScheduleAtFieldReadOnly TestScheduleWithMissingScheduleAtField => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithMissingScheduleAtFieldReadOnly TestScheduleWithMissingScheduleAtField => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutPrimaryKeyReadOnly TestScheduleWithoutPrimaryKey => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithoutPrimaryKeyReadOnly TestScheduleWithoutPrimaryKey => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutScheduleAtReadOnly TestScheduleWithoutScheduleAt => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithoutScheduleAtReadOnly TestScheduleWithoutScheduleAt => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly TestScheduleWithWrongPrimaryKeyType => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly TestScheduleWithWrongPrimaryKeyType => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly TestScheduleWithWrongScheduleAtType => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly TestScheduleWithWrongScheduleAtType => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestUniqueNotEquatableReadOnly TestUniqueNotEquatable => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestUniqueNotEquatableReadOnly TestUniqueNotEquatable => new(); } @@ -1103,27 +1103,27 @@ public static class LocalTableExtensions { extension(global::SpacetimeDB.Local db) { - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.Player Player => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.Player Player => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestAutoIncNotInteger TestAutoIncNotInteger => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestAutoIncNotInteger TestAutoIncNotInteger => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDefaultFieldValues TestDefaultFieldValues => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestDefaultFieldValues TestDefaultFieldValues => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDuplicateTableName TestDuplicateTableName => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestDuplicateTableName TestDuplicateTableName => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestIndexIssues TestIndexIssues => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestIndexIssues TestIndexIssues => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithMissingScheduleAtField TestScheduleWithMissingScheduleAtField => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithMissingScheduleAtField TestScheduleWithMissingScheduleAtField => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutPrimaryKey TestScheduleWithoutPrimaryKey => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithoutPrimaryKey TestScheduleWithoutPrimaryKey => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutScheduleAt TestScheduleWithoutScheduleAt => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithoutScheduleAt TestScheduleWithoutScheduleAt => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongPrimaryKeyType TestScheduleWithWrongPrimaryKeyType => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithWrongPrimaryKeyType TestScheduleWithWrongPrimaryKeyType => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongScheduleAtType TestScheduleWithWrongScheduleAtType => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithWrongScheduleAtType TestScheduleWithWrongScheduleAtType => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestUniqueNotEquatable TestUniqueNotEquatable => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestUniqueNotEquatable TestUniqueNotEquatable => new(); } } @@ -1132,27 +1132,27 @@ public static class ReadOnlyTableExtensions { extension(global::SpacetimeDB.Internal.LocalReadOnly db) { - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PlayerReadOnly Player => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.PlayerReadOnly Player => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestAutoIncNotIntegerReadOnly TestAutoIncNotInteger => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestAutoIncNotIntegerReadOnly TestAutoIncNotInteger => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestDefaultFieldValuesReadOnly TestDefaultFieldValues => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestDefaultFieldValuesReadOnly TestDefaultFieldValues => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestDuplicateTableNameReadOnly TestDuplicateTableName => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestDuplicateTableNameReadOnly TestDuplicateTableName => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestIndexIssuesReadOnly TestIndexIssues => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestIndexIssuesReadOnly TestIndexIssues => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithMissingScheduleAtFieldReadOnly TestScheduleWithMissingScheduleAtField => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithMissingScheduleAtFieldReadOnly TestScheduleWithMissingScheduleAtField => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutPrimaryKeyReadOnly TestScheduleWithoutPrimaryKey => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithoutPrimaryKeyReadOnly TestScheduleWithoutPrimaryKey => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutScheduleAtReadOnly TestScheduleWithoutScheduleAt => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithoutScheduleAtReadOnly TestScheduleWithoutScheduleAt => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly TestScheduleWithWrongPrimaryKeyType => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly TestScheduleWithWrongPrimaryKeyType => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly TestScheduleWithWrongScheduleAtType => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly TestScheduleWithWrongScheduleAtType => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestUniqueNotEquatableReadOnly TestUniqueNotEquatable => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestUniqueNotEquatableReadOnly TestUniqueNotEquatable => new(); } } @@ -2052,7 +2052,7 @@ public static partial class QueryTableExtensions } #endif -namespace SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles +namespace SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles { public readonly struct Player : global::SpacetimeDB.Internal.ITableView { @@ -4072,7 +4072,7 @@ public static byte[] Invoke( } } -namespace SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles +namespace SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles { public sealed class PlayerReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView @@ -4095,7 +4095,7 @@ internal PlayerReadOnly() public sealed class IdentityIndex : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PlayerReadOnly, + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.PlayerReadOnly, global::Player, SpacetimeDB.Identity, SpacetimeDB.Identity.BSATN @@ -4136,7 +4136,7 @@ internal TestAutoIncNotIntegerReadOnly() public sealed class IdentityFieldIndex : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestAutoIncNotIntegerReadOnly, + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestAutoIncNotIntegerReadOnly, global::TestAutoIncNotInteger, string, SpacetimeDB.BSATN.String @@ -4409,7 +4409,7 @@ internal TestScheduleWithoutScheduleAtReadOnly() public sealed class IdCorrectTypeIndex : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutScheduleAtReadOnly, + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithoutScheduleAtReadOnly, global::TestScheduleIssues, int, SpacetimeDB.BSATN.I32 @@ -4450,7 +4450,7 @@ internal TestScheduleWithWrongPrimaryKeyTypeReadOnly() public sealed class IdWrongTypeIndex : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly, + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly, global::TestScheduleIssues, string, SpacetimeDB.BSATN.String @@ -4491,7 +4491,7 @@ internal TestScheduleWithWrongScheduleAtTypeReadOnly() public sealed class IdCorrectTypeIndex : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly, + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly, global::TestScheduleIssues, int, SpacetimeDB.BSATN.I32 @@ -4532,7 +4532,7 @@ internal TestUniqueNotEquatableReadOnly() public sealed class PrimaryKeyFieldIndex : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestUniqueNotEquatableReadOnly, + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestUniqueNotEquatableReadOnly, global::TestUniqueNotEquatable, TestEnumWithExplicitValues, SpacetimeDB.BSATN.Enum @@ -4559,27 +4559,27 @@ namespace SpacetimeDB.Internal { public sealed partial class LocalReadOnly { - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PlayerReadOnly Player => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.PlayerReadOnly Player => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestAutoIncNotIntegerReadOnly TestAutoIncNotInteger => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestAutoIncNotIntegerReadOnly TestAutoIncNotInteger => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestDefaultFieldValuesReadOnly TestDefaultFieldValues => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestDefaultFieldValuesReadOnly TestDefaultFieldValues => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestDuplicateTableNameReadOnly TestDuplicateTableName => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestDuplicateTableNameReadOnly TestDuplicateTableName => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestIndexIssuesReadOnly TestIndexIssues => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestIndexIssuesReadOnly TestIndexIssues => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithMissingScheduleAtFieldReadOnly TestScheduleWithMissingScheduleAtField => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithMissingScheduleAtFieldReadOnly TestScheduleWithMissingScheduleAtField => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutPrimaryKeyReadOnly TestScheduleWithoutPrimaryKey => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithoutPrimaryKeyReadOnly TestScheduleWithoutPrimaryKey => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithoutScheduleAtReadOnly TestScheduleWithoutScheduleAt => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithoutScheduleAtReadOnly TestScheduleWithoutScheduleAt => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly TestScheduleWithWrongPrimaryKeyType => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly TestScheduleWithWrongPrimaryKeyType => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly TestScheduleWithWrongScheduleAtType => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly TestScheduleWithWrongScheduleAtType => new(); - public global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.TestUniqueNotEquatableReadOnly TestUniqueNotEquatable => + public global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles.TestUniqueNotEquatableReadOnly TestUniqueNotEquatable => new(); } } @@ -4817,7 +4817,7 @@ internal static void Initialize() new global::System.Collections.Generic.KeyValuePair[] { } ) ); - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Register( + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Register( global::SpacetimeDB.Internal.Module.RootBuilder ); #else @@ -4882,47 +4882,47 @@ internal static void Register( builder.RegisterTable< global::Player, - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.Player + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.Player >(); builder.RegisterTable< global::TestAutoIncNotInteger, - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestAutoIncNotInteger + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestAutoIncNotInteger >(); builder.RegisterTable< global::TestDefaultFieldValues, - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDefaultFieldValues + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestDefaultFieldValues >(); builder.RegisterTable< global::TestDuplicateTableName, - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestDuplicateTableName + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestDuplicateTableName >(); builder.RegisterTable< global::TestIndexIssues, - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestIndexIssues + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestIndexIssues >(); builder.RegisterTable< global::TestScheduleIssues, - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithMissingScheduleAtField + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithMissingScheduleAtField >(); builder.RegisterTable< global::TestScheduleIssues, - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutPrimaryKey + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithoutPrimaryKey >(); builder.RegisterTable< global::TestScheduleIssues, - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithoutScheduleAt + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithoutScheduleAt >(); builder.RegisterTable< global::TestScheduleIssues, - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongPrimaryKeyType + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithWrongPrimaryKeyType >(); builder.RegisterTable< global::TestScheduleIssues, - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestScheduleWithWrongScheduleAtType + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestScheduleWithWrongScheduleAtType >(); builder.RegisterTable< global::TestUniqueNotEquatable, - global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.TestUniqueNotEquatable + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.TableHandles.TestUniqueNotEquatable >(); builder.RegisterClientVisibilityFilter(global::Module.MY_FILTER); @@ -5873,13 +5873,9 @@ SpacetimeDB.Internal.BytesSink error if ( (uint)localId < (uint) - global::SpacetimeDB - .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C - .AssemblyDescriptor - .ReducerCount + global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.ReducerCount ) - return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalReducer( + return global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.CallLocalReducer( localId, sender_0, sender_1, @@ -5893,7 +5889,7 @@ SpacetimeDB.Internal.BytesSink error ); localId -= global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .ReducerCount; return SpacetimeDB.Internal.Module.WriteReducerError( @@ -6051,11 +6047,11 @@ SpacetimeDB.Internal.BytesSink result_sink < (uint) global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .ProcedureCount ) - return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalProcedure( + return global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.CallLocalProcedure( localId, sender_0, sender_1, @@ -6069,7 +6065,7 @@ SpacetimeDB.Internal.BytesSink result_sink ); localId -= global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .ProcedureCount; throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); @@ -6133,11 +6129,11 @@ SpacetimeDB.Internal.BytesSink response_body_sink < (uint) global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .HttpHandlerCount ) - return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalHttpHandler( + return global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.CallLocalHttpHandler( localId, timestamp, request, @@ -6147,7 +6143,7 @@ SpacetimeDB.Internal.BytesSink response_body_sink ); localId -= global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .HttpHandlerCount; throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); @@ -6201,14 +6197,9 @@ SpacetimeDB.Internal.BytesSink sink var localId = id; if ( (uint)localId - < (uint) - global::SpacetimeDB - .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C - .AssemblyDescriptor - .ViewCount + < (uint)global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.ViewCount ) - return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalView( + return global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.CallLocalView( localId, sender_0, sender_1, @@ -6217,11 +6208,7 @@ SpacetimeDB.Internal.BytesSink sink args, sink ); - localId -= global::SpacetimeDB - .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C - .AssemblyDescriptor - .ViewCount; + localId -= global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.ViewCount; return UnknownViewId(id); #else return CallLocalView(id, sender_0, sender_1, sender_2, sender_3, args, sink); @@ -6274,18 +6261,18 @@ SpacetimeDB.Internal.BytesSink sink < (uint) global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .AnonymousViewCount ) - return global::SpacetimeDB.Generated.Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalAnonymousView( + return global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.CallLocalAnonymousView( localId, args, sink ); localId -= global::SpacetimeDB .Generated - .Assembly_0064006900610067002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .diag_4F830E2879BB50E3 .AssemblyDescriptor .AnonymousViewCount; return UnknownAnonymousViewId(id); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs index fcaf4a85b89..fb831299a43 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs @@ -6,7 +6,7 @@ #pragma warning disable STDB_UNSTABLE #if NET10_0_OR_GREATER -global using SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C; +global using SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31; #endif using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; @@ -15,7 +15,7 @@ using TxContext = SpacetimeDB.Internal.TxContext; #if NET10_0_OR_GREATER [assembly: global::SpacetimeDB.ModuleDescriptorAttribute( - typeof(global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor) + typeof(global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor) )] #endif @@ -316,7 +316,7 @@ internal AnonymousViewContext(Internal.LocalReadOnly db) } #if NET10_0_OR_GREATER -namespace SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +namespace SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31 { public static partial class AssemblyDescriptor { @@ -835,7 +835,7 @@ internal static void Initialize() new global::System.Collections.Generic.KeyValuePair[] { } ) ); - global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Register( + global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.Register( global::SpacetimeDB.Internal.Module.RootBuilder ); #else @@ -1019,11 +1019,11 @@ SpacetimeDB.Internal.BytesSink error < (uint) global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .ReducerCount ) - return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalReducer( + return global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.CallLocalReducer( localId, sender_0, sender_1, @@ -1037,7 +1037,7 @@ SpacetimeDB.Internal.BytesSink error ); localId -= global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .ReducerCount; return SpacetimeDB.Internal.Module.WriteReducerError( @@ -1118,11 +1118,11 @@ SpacetimeDB.Internal.BytesSink result_sink < (uint) global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .ProcedureCount ) - return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalProcedure( + return global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.CallLocalProcedure( localId, sender_0, sender_1, @@ -1136,7 +1136,7 @@ SpacetimeDB.Internal.BytesSink result_sink ); localId -= global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .ProcedureCount; throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); @@ -1211,11 +1211,11 @@ SpacetimeDB.Internal.BytesSink response_body_sink < (uint) global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .HttpHandlerCount ) - return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalHttpHandler( + return global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.CallLocalHttpHandler( localId, timestamp, request, @@ -1225,7 +1225,7 @@ SpacetimeDB.Internal.BytesSink response_body_sink ); localId -= global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .HttpHandlerCount; throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); @@ -1282,11 +1282,11 @@ SpacetimeDB.Internal.BytesSink sink < (uint) global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .ViewCount ) - return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalView( + return global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.CallLocalView( localId, sender_0, sender_1, @@ -1297,7 +1297,7 @@ SpacetimeDB.Internal.BytesSink sink ); localId -= global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .ViewCount; return UnknownViewId(id); @@ -1341,18 +1341,18 @@ SpacetimeDB.Internal.BytesSink sink < (uint) global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .AnonymousViewCount ) - return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalAnonymousView( + return global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.CallLocalAnonymousView( localId, args, sink ); localId -= global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .AnonymousViewCount; return UnknownAnonymousViewId(id); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs index 7647b610817..baec61ee65b 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs @@ -6,7 +6,7 @@ #pragma warning disable STDB_UNSTABLE #if NET10_0_OR_GREATER -global using SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C; +global using SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31; #endif using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; @@ -15,7 +15,7 @@ using TxContext = SpacetimeDB.Internal.TxContext; #if NET10_0_OR_GREATER [assembly: global::SpacetimeDB.ModuleDescriptorAttribute( - typeof(global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor) + typeof(global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor) )] #endif @@ -285,7 +285,7 @@ internal HandlerTxContext(Internal.TxContext inner) public sealed class Local : global::SpacetimeDB.LocalBase { - public global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.DemoTable DemoTable => + public global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.TableHandles.DemoTable DemoTable => new(); } @@ -317,7 +317,7 @@ internal AnonymousViewContext(Internal.LocalReadOnly db) } #if NET10_0_OR_GREATER -namespace SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +namespace SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31 { public static partial class AssemblyDescriptor { @@ -427,13 +427,13 @@ public static void Register( public readonly struct Tables { - public global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.DemoTable DemoTable => + public global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.TableHandles.DemoTable DemoTable => new(); } public readonly struct ReadOnlyTables { - public global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.DemoTableReadOnly DemoTable => + public global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.ViewHandles.DemoTableReadOnly DemoTable => new(); } @@ -444,7 +444,7 @@ public static class LocalTableExtensions { extension(global::SpacetimeDB.Local db) { - public global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.DemoTable DemoTable => + public global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.TableHandles.DemoTable DemoTable => new(); } } @@ -453,7 +453,7 @@ public static class ReadOnlyTableExtensions { extension(global::SpacetimeDB.Internal.LocalReadOnly db) { - public global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.DemoTableReadOnly DemoTable => + public global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.ViewHandles.DemoTableReadOnly DemoTable => new(); } } @@ -518,7 +518,7 @@ public static partial class QueryTableExtensions } #endif -namespace SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles +namespace SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.TableHandles { public readonly struct DemoTable : global::SpacetimeDB.Internal.ITableView @@ -688,7 +688,7 @@ public static byte[] Invoke( } } -namespace SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles +namespace SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.ViewHandles { public sealed class DemoTableReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView @@ -711,7 +711,7 @@ internal DemoTableReadOnly() public sealed class IdIndex : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.DemoTableReadOnly, + global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.ViewHandles.DemoTableReadOnly, global::DemoTable, int, SpacetimeDB.BSATN.I32 @@ -765,7 +765,7 @@ namespace SpacetimeDB.Internal { public sealed partial class LocalReadOnly { - public global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.DemoTableReadOnly DemoTable => + public global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.ViewHandles.DemoTableReadOnly DemoTable => new(); } } @@ -872,7 +872,7 @@ internal static void Initialize() new global::System.Collections.Generic.KeyValuePair[] { } ) ); - global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Register( + global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.Register( global::SpacetimeDB.Internal.Module.RootBuilder ); #else @@ -906,7 +906,7 @@ internal static void Register( builder.RegisterTable< global::DemoTable, - global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.DemoTable + global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.TableHandles.DemoTable >(); } @@ -1056,11 +1056,11 @@ SpacetimeDB.Internal.BytesSink error < (uint) global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .ReducerCount ) - return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalReducer( + return global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.CallLocalReducer( localId, sender_0, sender_1, @@ -1074,7 +1074,7 @@ SpacetimeDB.Internal.BytesSink error ); localId -= global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .ReducerCount; return SpacetimeDB.Internal.Module.WriteReducerError( @@ -1155,11 +1155,11 @@ SpacetimeDB.Internal.BytesSink result_sink < (uint) global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .ProcedureCount ) - return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalProcedure( + return global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.CallLocalProcedure( localId, sender_0, sender_1, @@ -1173,7 +1173,7 @@ SpacetimeDB.Internal.BytesSink result_sink ); localId -= global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .ProcedureCount; throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); @@ -1248,11 +1248,11 @@ SpacetimeDB.Internal.BytesSink response_body_sink < (uint) global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .HttpHandlerCount ) - return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalHttpHandler( + return global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.CallLocalHttpHandler( localId, timestamp, request, @@ -1262,7 +1262,7 @@ SpacetimeDB.Internal.BytesSink response_body_sink ); localId -= global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .HttpHandlerCount; throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); @@ -1319,11 +1319,11 @@ SpacetimeDB.Internal.BytesSink sink < (uint) global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .ViewCount ) - return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalView( + return global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.CallLocalView( localId, sender_0, sender_1, @@ -1334,7 +1334,7 @@ SpacetimeDB.Internal.BytesSink sink ); localId -= global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .ViewCount; return UnknownViewId(id); @@ -1378,18 +1378,18 @@ SpacetimeDB.Internal.BytesSink sink < (uint) global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .AnonymousViewCount ) - return global::SpacetimeDB.Generated.Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalAnonymousView( + return global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.CallLocalAnonymousView( localId, args, sink ); localId -= global::SpacetimeDB .Generated - .Assembly_006500780070006C0069006300690074006E0061006D00650073002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .explicitnames_7C0F8C6449994F31 .AssemblyDescriptor .AnonymousViewCount; return UnknownAnonymousViewId(id); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/EnvironmentGenerator.net10#Environment.g.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/EnvironmentGenerator.net10#Environment.g.verified.cs index eeb542f1cb9..4ce133f61e1 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/EnvironmentGenerator.net10#Environment.g.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/EnvironmentGenerator.net10#Environment.g.verified.cs @@ -1,7 +1,7 @@ //HintName: Environment.g.cs // #nullable enable -namespace SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +namespace SpacetimeDB.Generated.server_D513E4815F57969C { public static class EnvironmentExtensions { diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs index 3334192d387..760693ed7b2 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs @@ -6,7 +6,7 @@ #pragma warning disable STDB_UNSTABLE #if NET10_0_OR_GREATER -global using SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C; +global using SpacetimeDB.Generated.server_D513E4815F57969C; #endif using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; @@ -15,7 +15,7 @@ using TxContext = SpacetimeDB.Internal.TxContext; #if NET10_0_OR_GREATER [assembly: global::SpacetimeDB.ModuleDescriptorAttribute( - typeof(global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor) + typeof(global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor) )] #endif @@ -767,7 +767,7 @@ internal AnonymousViewContext(Internal.LocalReadOnly db) } #if NET10_0_OR_GREATER -namespace SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +namespace SpacetimeDB.Generated.server_D513E4815F57969C { public static partial class AssemblyDescriptor { @@ -3397,7 +3397,7 @@ internal static void Initialize() new global::System.Collections.Generic.KeyValuePair[] { } ) ); - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Register( + global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.Register( global::SpacetimeDB.Internal.Module.RootBuilder ); #else @@ -3816,11 +3816,11 @@ SpacetimeDB.Internal.BytesSink error < (uint) global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .ReducerCount ) - return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalReducer( + return global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.CallLocalReducer( localId, sender_0, sender_1, @@ -3834,7 +3834,7 @@ SpacetimeDB.Internal.BytesSink error ); localId -= global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .ReducerCount; return SpacetimeDB.Internal.Module.WriteReducerError( @@ -3970,11 +3970,11 @@ SpacetimeDB.Internal.BytesSink result_sink < (uint) global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .ProcedureCount ) - return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalProcedure( + return global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.CallLocalProcedure( localId, sender_0, sender_1, @@ -3988,7 +3988,7 @@ SpacetimeDB.Internal.BytesSink result_sink ); localId -= global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .ProcedureCount; throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); @@ -4052,11 +4052,11 @@ SpacetimeDB.Internal.BytesSink response_body_sink < (uint) global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .HttpHandlerCount ) - return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalHttpHandler( + return global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.CallLocalHttpHandler( localId, timestamp, request, @@ -4066,7 +4066,7 @@ SpacetimeDB.Internal.BytesSink response_body_sink ); localId -= global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .HttpHandlerCount; throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); @@ -4121,13 +4121,9 @@ SpacetimeDB.Internal.BytesSink sink if ( (uint)localId < (uint) - global::SpacetimeDB - .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C - .AssemblyDescriptor - .ViewCount + global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.ViewCount ) - return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalView( + return global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.CallLocalView( localId, sender_0, sender_1, @@ -4138,7 +4134,7 @@ SpacetimeDB.Internal.BytesSink sink ); localId -= global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .ViewCount; return UnknownViewId(id); @@ -4183,18 +4179,18 @@ SpacetimeDB.Internal.BytesSink sink < (uint) global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .AnonymousViewCount ) - return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalAnonymousView( + return global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.CallLocalAnonymousView( localId, args, sink ); localId -= global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .AnonymousViewCount; return UnknownAnonymousViewId(id); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs index 34cd7c912be..07336d4dbfd 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs @@ -6,7 +6,7 @@ #pragma warning disable STDB_UNSTABLE #if NET10_0_OR_GREATER -global using SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C; +global using SpacetimeDB.Generated.server_D513E4815F57969C; #endif using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; @@ -15,7 +15,7 @@ using TxContext = SpacetimeDB.Internal.TxContext; #if NET10_0_OR_GREATER [assembly: global::SpacetimeDB.ModuleDescriptorAttribute( - typeof(global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor) + typeof(global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor) )] #endif @@ -727,21 +727,21 @@ internal HandlerTxContext(Internal.TxContext inner) public sealed class Local : global::SpacetimeDB.LocalBase { - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeMultiColumn BTreeMultiColumn => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.BTreeMultiColumn BTreeMultiColumn => new(); - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeViews BTreeViews => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.BTreeViews BTreeViews => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable1 MultiTable1 => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.MultiTable1 MultiTable1 => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable2 MultiTable2 => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.MultiTable2 MultiTable2 => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PrivateTable PrivateTable => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.PrivateTable PrivateTable => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PublicTable PublicTable => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.PublicTable PublicTable => new(); - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.SendMessageTimer SendMessageTimer => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.SendMessageTimer SendMessageTimer => new(); } @@ -773,7 +773,7 @@ internal AnonymousViewContext(Internal.LocalReadOnly db) } #if NET10_0_OR_GREATER -namespace SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C +namespace SpacetimeDB.Generated.server_D513E4815F57969C { public static partial class AssemblyDescriptor { @@ -883,41 +883,41 @@ public static void Register( public readonly struct Tables { - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeMultiColumn BTreeMultiColumn => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.BTreeMultiColumn BTreeMultiColumn => new(); - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeViews BTreeViews => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.BTreeViews BTreeViews => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable1 MultiTable1 => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.MultiTable1 MultiTable1 => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable2 MultiTable2 => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.MultiTable2 MultiTable2 => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PrivateTable PrivateTable => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.PrivateTable PrivateTable => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PublicTable PublicTable => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.PublicTable PublicTable => new(); - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.SendMessageTimer SendMessageTimer => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.SendMessageTimer SendMessageTimer => new(); } public readonly struct ReadOnlyTables { - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeMultiColumnReadOnly BTreeMultiColumn => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.BTreeMultiColumnReadOnly BTreeMultiColumn => new(); - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeViewsReadOnly BTreeViews => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.BTreeViewsReadOnly BTreeViews => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable1ReadOnly MultiTable1 => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.MultiTable1ReadOnly MultiTable1 => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable2ReadOnly MultiTable2 => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.MultiTable2ReadOnly MultiTable2 => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PrivateTableReadOnly PrivateTable => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.PrivateTableReadOnly PrivateTable => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PublicTableReadOnly PublicTable => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.PublicTableReadOnly PublicTable => new(); - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly RegressionMultipleUniqueIndexesHadSameName => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly RegressionMultipleUniqueIndexesHadSameName => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.SendMessageTimerReadOnly SendMessageTimer => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.SendMessageTimerReadOnly SendMessageTimer => new(); } @@ -928,21 +928,21 @@ public static class LocalTableExtensions { extension(global::SpacetimeDB.Local db) { - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeMultiColumn BTreeMultiColumn => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.BTreeMultiColumn BTreeMultiColumn => new(); - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeViews BTreeViews => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.BTreeViews BTreeViews => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable1 MultiTable1 => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.MultiTable1 MultiTable1 => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable2 MultiTable2 => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.MultiTable2 MultiTable2 => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PrivateTable PrivateTable => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.PrivateTable PrivateTable => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PublicTable PublicTable => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.PublicTable PublicTable => new(); - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.SendMessageTimer SendMessageTimer => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.SendMessageTimer SendMessageTimer => new(); } } @@ -951,21 +951,21 @@ public static class ReadOnlyTableExtensions { extension(global::SpacetimeDB.Internal.LocalReadOnly db) { - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeMultiColumnReadOnly BTreeMultiColumn => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.BTreeMultiColumnReadOnly BTreeMultiColumn => new(); - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeViewsReadOnly BTreeViews => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.BTreeViewsReadOnly BTreeViews => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable1ReadOnly MultiTable1 => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.MultiTable1ReadOnly MultiTable1 => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable2ReadOnly MultiTable2 => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.MultiTable2ReadOnly MultiTable2 => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PrivateTableReadOnly PrivateTable => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.PrivateTableReadOnly PrivateTable => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PublicTableReadOnly PublicTable => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.PublicTableReadOnly PublicTable => new(); - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly RegressionMultipleUniqueIndexesHadSameName => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly RegressionMultipleUniqueIndexesHadSameName => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.SendMessageTimerReadOnly SendMessageTimer => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.SendMessageTimerReadOnly SendMessageTimer => new(); } } @@ -1624,7 +1624,7 @@ public static partial class QueryTableExtensions } #endif -namespace SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles +namespace SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles { internal readonly struct BTreeMultiColumn : global::SpacetimeDB.Internal.ITableView @@ -2887,7 +2887,7 @@ public static byte[] Invoke( } } -namespace SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles +namespace SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles { internal sealed class BTreeMultiColumnReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView @@ -3008,7 +3008,7 @@ internal BTreeViewsReadOnly() public sealed class IdIndex : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeViewsReadOnly, + global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.BTreeViewsReadOnly, global::BTreeViews, SpacetimeDB.Identity, SpacetimeDB.Identity.BSATN @@ -3131,7 +3131,7 @@ internal MultiTable1ReadOnly() public sealed class FooIndex : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable1ReadOnly, + global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.MultiTable1ReadOnly, global::MultiTableRow, uint, SpacetimeDB.BSATN.U32 @@ -3204,7 +3204,7 @@ internal MultiTable2ReadOnly() public sealed class BarIndex : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable2ReadOnly, + global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.MultiTable2ReadOnly, global::MultiTableRow, uint, SpacetimeDB.BSATN.U32 @@ -3265,7 +3265,7 @@ internal PublicTableReadOnly() public sealed class IdIndex : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PublicTableReadOnly, + global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.PublicTableReadOnly, global::PublicTable, int, SpacetimeDB.BSATN.I32 @@ -3306,7 +3306,7 @@ internal RegressionMultipleUniqueIndexesHadSameNameReadOnly() public sealed class Unique1Index : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly, + global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly, global::RegressionMultipleUniqueIndexesHadSameName, uint, SpacetimeDB.BSATN.U32 @@ -3328,7 +3328,7 @@ internal Unique1Index() public sealed class Unique2Index : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly, + global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly, global::RegressionMultipleUniqueIndexesHadSameName, uint, SpacetimeDB.BSATN.U32 @@ -3370,7 +3370,7 @@ internal SendMessageTimerReadOnly() public sealed class ScheduledIdIndex : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.SendMessageTimerReadOnly, + global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.SendMessageTimerReadOnly, global::Timers.SendMessageTimer, ulong, SpacetimeDB.BSATN.U64 @@ -3396,21 +3396,21 @@ namespace SpacetimeDB.Internal { public sealed partial class LocalReadOnly { - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeMultiColumnReadOnly BTreeMultiColumn => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.BTreeMultiColumnReadOnly BTreeMultiColumn => new(); - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.BTreeViewsReadOnly BTreeViews => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.BTreeViewsReadOnly BTreeViews => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable1ReadOnly MultiTable1 => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.MultiTable1ReadOnly MultiTable1 => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.MultiTable2ReadOnly MultiTable2 => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.MultiTable2ReadOnly MultiTable2 => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PrivateTableReadOnly PrivateTable => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.PrivateTableReadOnly PrivateTable => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.PublicTableReadOnly PublicTable => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.PublicTableReadOnly PublicTable => new(); - internal global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly RegressionMultipleUniqueIndexesHadSameName => + internal global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly RegressionMultipleUniqueIndexesHadSameName => new(); - public global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.ViewHandles.SendMessageTimerReadOnly SendMessageTimer => + public global::SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles.SendMessageTimerReadOnly SendMessageTimer => new(); } } @@ -3614,7 +3614,7 @@ internal static void Initialize() new global::System.Collections.Generic.KeyValuePair[] { } ) ); - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.Register( + global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.Register( global::SpacetimeDB.Internal.Module.RootBuilder ); #else @@ -3663,35 +3663,35 @@ internal static void Register( builder.RegisterTable< global::BTreeMultiColumn, - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeMultiColumn + global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.BTreeMultiColumn >(); builder.RegisterTable< global::BTreeViews, - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.BTreeViews + global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.BTreeViews >(); builder.RegisterTable< global::MultiTableRow, - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable1 + global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.MultiTable1 >(); builder.RegisterTable< global::MultiTableRow, - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.MultiTable2 + global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.MultiTable2 >(); builder.RegisterTable< global::PrivateTable, - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PrivateTable + global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.PrivateTable >(); builder.RegisterTable< global::PublicTable, - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.PublicTable + global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.PublicTable >(); builder.RegisterTable< global::RegressionMultipleUniqueIndexesHadSameName, - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.RegressionMultipleUniqueIndexesHadSameName + global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.RegressionMultipleUniqueIndexesHadSameName >(); builder.RegisterTable< global::Timers.SendMessageTimer, - global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.TableHandles.SendMessageTimer + global::SpacetimeDB.Generated.server_D513E4815F57969C.TableHandles.SendMessageTimer >(); builder.RegisterClientVisibilityFilter(global::Module.ALL_PUBLIC_TABLES); @@ -4047,11 +4047,11 @@ SpacetimeDB.Internal.BytesSink error < (uint) global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .ReducerCount ) - return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalReducer( + return global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.CallLocalReducer( localId, sender_0, sender_1, @@ -4065,7 +4065,7 @@ SpacetimeDB.Internal.BytesSink error ); localId -= global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .ReducerCount; return SpacetimeDB.Internal.Module.WriteReducerError( @@ -4201,11 +4201,11 @@ SpacetimeDB.Internal.BytesSink result_sink < (uint) global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .ProcedureCount ) - return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalProcedure( + return global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.CallLocalProcedure( localId, sender_0, sender_1, @@ -4219,7 +4219,7 @@ SpacetimeDB.Internal.BytesSink result_sink ); localId -= global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .ProcedureCount; throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown procedure id"); @@ -4283,11 +4283,11 @@ SpacetimeDB.Internal.BytesSink response_body_sink < (uint) global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .HttpHandlerCount ) - return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalHttpHandler( + return global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.CallLocalHttpHandler( localId, timestamp, request, @@ -4297,7 +4297,7 @@ SpacetimeDB.Internal.BytesSink response_body_sink ); localId -= global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .HttpHandlerCount; throw new System.ArgumentOutOfRangeException(nameof(id), id, "Unknown HTTP handler id"); @@ -4352,13 +4352,9 @@ SpacetimeDB.Internal.BytesSink sink if ( (uint)localId < (uint) - global::SpacetimeDB - .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C - .AssemblyDescriptor - .ViewCount + global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.ViewCount ) - return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalView( + return global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.CallLocalView( localId, sender_0, sender_1, @@ -4369,7 +4365,7 @@ SpacetimeDB.Internal.BytesSink sink ); localId -= global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .ViewCount; return UnknownViewId(id); @@ -4414,18 +4410,18 @@ SpacetimeDB.Internal.BytesSink sink < (uint) global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .AnonymousViewCount ) - return global::SpacetimeDB.Generated.Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C.AssemblyDescriptor.CallLocalAnonymousView( + return global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.CallLocalAnonymousView( localId, args, sink ); localId -= global::SpacetimeDB .Generated - .Assembly_007300650072007600650072002C002000560065007200730069006F006E003D0031002E0030002E0030002E0030002C002000430075006C0074007500720065003D006E00650075007400720061006C002C0020005000750062006C00690063004B006500790054006F006B0065006E003D006E0075006C006C + .server_D513E4815F57969C .AssemblyDescriptor .AnonymousViewCount; return UnknownAnonymousViewId(id); diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs index f17f888e1c8..b6f5cd73dfa 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.4.1 (commit ed95086da83809e1e621aae0066b0970a4130a3e). +// This was generated using spacetimedb cli version 2.10.1 (commit 7109fe86a665ba5404389ce72ffc63131bf576cc). #nullable enable diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs index 2933600fd49..6241c5db4b6 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.10.1 (commit fc03797a117b64e157e2bc7e35628c7ac960aa18). +// This was generated using spacetimedb cli version 2.10.1 (commit 7109fe86a665ba5404389ce72ffc63131bf576cc). #nullable enable @@ -502,7 +502,7 @@ public TypedSubscriptionBuilder AddQuery( /// Data from all the provided queries will be returned at the same time. /// /// See the SpacetimeDB SQL docs for more information on SQL syntax: - /// https://spacetimedb.com/docs/sql + /// https://spacetimedb.com/docs/reference/sql /// public SubscriptionHandle Subscribe( string[] querySqls diff --git a/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs index 4bdf39df0a8..f769484f301 100644 --- a/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.4 (commit dfc726be29516b8cdecc651f5c9705026a624a04). +// This was generated using spacetimedb cli version 2.10.1 (commit 7109fe86a665ba5404389ce72ffc63131bf576cc). #nullable enable diff --git a/sdks/csharp/examples~/regression-tests/republishing/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/republishing/client/module_bindings/SpacetimeDBClient.g.cs index 446d0a75382..670d39676c5 100644 --- a/sdks/csharp/examples~/regression-tests/republishing/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/republishing/client/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.0 (commit 4cce69765507c1815979d39572b4a52864f5c3d2). +// This was generated using spacetimedb cli version 2.10.1 (commit 7109fe86a665ba5404389ce72ffc63131bf576cc). #nullable enable From c9e40c6232a2a916de59851d9e38c5ac454385fd Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Mon, 21 Sep 2026 12:37:44 -0500 Subject: [PATCH 20/49] Clean Runtime/Internal/Module.cs --- .../Runtime/Internal/Module.cs | 64 ++++++++----------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index 123dac56ada..c3dcad6ad1a 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -41,15 +41,17 @@ private static void EnsureNativeAotTypeRoots() } } - private static readonly ModuleBuilder moduleDef = new(); - public static ModuleBuilder RootBuilder => moduleDef; + public static readonly ModuleBuilder RootBuilder = new(); private static NamespaceRegistry? namespaces; public static void InstallNamespaces(NamespaceRegistry registry) { if (namespaces is not null) + { throw new InvalidOperationException("Module namespaces have already been installed."); + } + namespaces = registry; } @@ -131,7 +133,7 @@ public static void SetAnonymousViewContextConstructor(Func this.target = target; @@ -156,68 +158,56 @@ public AlgebraicType.Ref RegisterType(Func } public static void RegisterReducer() - where R : IReducer, new() - { - moduleDef.RegisterReducer(); - } + where R : IReducer, new() => + RootBuilder.RegisterReducer(); public static void RegisterProcedure

() - where P : IProcedure, new() - { - moduleDef.RegisterProcedure

(); - } + where P : IProcedure, new() => + RootBuilder.RegisterProcedure

(); public static void RegisterHttpHandler() - where H : IHttpHandler, new() - { - moduleDef.RegisterHttpHandler(); - } + where H : IHttpHandler, new() => + RootBuilder.RegisterHttpHandler(); public static void RegisterHttpRouter(SpacetimeDB.Router router) => - moduleDef.RegisterHttpRouter(router); + RootBuilder.RegisterHttpRouter(router); public static void RegisterTable() where T : IStructuralReadWrite, new() - where View : ITableView, new() - { - moduleDef.RegisterTable(); - } + where View : ITableView, new() => + RootBuilder.RegisterTable(); public static void RegisterView() - where TDispatcher : IView, new() - { - moduleDef.RegisterView(); - } + where TDispatcher : IView, new() => + RootBuilder.RegisterView(); public static void RegisterAnonymousView() - where TDispatcher : IAnonymousView, new() - { - moduleDef.RegisterAnonymousView(); - } + where TDispatcher : IAnonymousView, new() => + RootBuilder.RegisterAnonymousView(); public static void RegisterEnvironment(EnvironmentDeclaration declaration) => - moduleDef.RegisterEnvironment(declaration); + RootBuilder.RegisterEnvironment(declaration); public static void RegisterViewPrimaryKey(string viewSourceName, string[] columns) => - moduleDef.RegisterViewPrimaryKey(viewSourceName, columns); + RootBuilder.RegisterViewPrimaryKey(viewSourceName, columns); public static void RegisterClientVisibilityFilter(Filter rlsFilter) => - moduleDef.RegisterClientVisibilityFilter(rlsFilter); + RootBuilder.RegisterClientVisibilityFilter(rlsFilter); public static void RegisterTableDefaultValue(string table, ushort colId, byte[] value) => - moduleDef.RegisterTableDefaultValue(table, colId, value); + RootBuilder.RegisterTableDefaultValue(table, colId, value); public static void SetCaseConversionPolicy(SpacetimeDB.CaseConversionPolicy policy) => - moduleDef.SetCaseConversionPolicy(policy); + RootBuilder.SetCaseConversionPolicy(policy); public static void RegisterExplicitTableName(string sourceName, string canonicalName) => - moduleDef.RegisterExplicitTableName(sourceName, canonicalName); + RootBuilder.RegisterExplicitTableName(sourceName, canonicalName); public static void RegisterExplicitFunctionName(string sourceName, string canonicalName) => - moduleDef.RegisterExplicitFunctionName(sourceName, canonicalName); + RootBuilder.RegisterExplicitFunctionName(sourceName, canonicalName); public static void RegisterExplicitIndexName(string sourceName, string canonicalName) => - moduleDef.RegisterExplicitIndexName(sourceName, canonicalName); + RootBuilder.RegisterExplicitIndexName(sourceName, canonicalName); public static byte[] Consume(this BytesSource source) { @@ -406,7 +396,7 @@ public static void __describe_module__(BytesSink description) EnsureNativeAotTypeRoots(); try { - var module = moduleDef.BuildModuleDefinition(); + var module = RootBuilder.BuildModuleDefinition(); RawModuleDef versioned = new RawModuleDef.V10(module); var moduleBytes = IStructuralReadWrite.ToBytes(new RawModuleDef.BSATN(), versioned); description.Write(moduleBytes); From 9c85479f509217e8f1c0e0a09599614bffd47f6a Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Mon, 21 Sep 2026 13:16:15 -0500 Subject: [PATCH 21/49] Increase test coverage --- .../tests/standalone_integration_test.rs | 81 ++++++++++++++++++- modules/namespace-test-cs/Lib.cs | 18 +++++ .../Procedures/CountAuthUsers.g.cs | 64 +++++++++++++++ .../module_bindings/Reducers/AddAuthUser.g.cs | 66 +++++++++++++++ .../module_bindings/SpacetimeDBClient.g.cs | 1 + 5 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/CountAuthUsers.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/AddAuthUser.g.cs diff --git a/crates/testing/tests/standalone_integration_test.rs b/crates/testing/tests/standalone_integration_test.rs index 2ffccce1790..30965fe09c0 100644 --- a/crates/testing/tests/standalone_integration_test.rs +++ b/crates/testing/tests/standalone_integration_test.rs @@ -130,6 +130,50 @@ fn namespace_csharp_root_selected_at_publish() { ); } +#[test] +#[serial] +fn namespace_csharp_cross_namespace_calls() { + init(); + CompiledModule::compile("namespace-test-cs", CompilationMode::Debug).with_module_async( + DEFAULT_CONFIG, + |mut module| async move { + // Mirror test_submodule_in_module: enter the root through the websocket API, + // then delegate to exported library callbacks using the same context object. + module + .send_reducer_and_recv_update( + r#"{"CallReducer":{"reducer":"add_auth_user","args":"[12]","request_id":0,"flags":0}}"#.to_string(), + 0, + ) + .await + .unwrap(); + assert_eq!(read_logs(&module).await, ["Auth users: 1"]); + assert_eq!( + module.call_procedure_with_args("count_auth_users", "[]").await.unwrap(), + AlgebraicValue::U64(1) + ); + assert_eq!( + module.call_http_route_get("/root-auth-count").await.unwrap().as_ref(), + b"1" + ); + + // The library's own route remains registered alongside the root's route. + assert_eq!(module.call_http_route_get("/auth-count").await.unwrap().as_ref(), b"1"); + assert_eq!( + module + .call_procedure_with_args("class.count_users", "[]") + .await + .unwrap(), + AlgebraicValue::U64(0) + ); + assert_eq!( + module.call_procedure_with_args("count_users", "[]").await.unwrap(), + AlgebraicValue::U64(1), + "delegation must not also insert into the root or Audit table" + ); + }, + ); +} + #[test] #[serial] fn namespace_csharp_mounted_dependencies() { @@ -193,10 +237,43 @@ fn namespace_csharp_mounted_dependencies() { tokio::time::timeout(Duration::from_secs(10), async { while let Some(message) = module.recv_message().await { if let spacetimedb::client::OutboundMessage::V1( - message @ spacetimedb::client::messages::SerializableMessage::Subscribe(_), + spacetimedb::client::messages::SerializableMessage::Subscribe(update), ) = message { - assert_eq!(message.num_rows(), Some(9)); + use spacetimedb_client_api_messages::websocket::v1::{ + DatabaseUpdate, FormatSwitch, WebsocketFormat, + }; + fn table_counts( + update: DatabaseUpdate, + ) -> std::collections::BTreeMap { + assert_eq!(update.tables.len(), 9, "one update per subscribed table/view"); + update + .tables + .into_iter() + .map(|table| (table.table_name.to_string(), table.num_rows)) + .collect() + } + assert_eq!(update.request_id, Some(99)); + let counts = match update.database_update { + FormatSwitch::Bsatn(update) => table_counts(update), + FormatSwitch::Json(update) => table_counts(update), + }; + assert_eq!( + counts, + [ + ("users", 1), + ("auth_users", 1), + ("extra_rows", 1), + ("MyAuth.users", 1), + ("MyAuth.anonymous_users", 1), + ("query_users", 1), + ("query_users_right", 1), + ("query_extra", 1), + ("MyAuth.query_users", 1), + ] + .map(|(name, count)| (name.to_owned(), count)) + .into() + ); return; } } diff --git a/modules/namespace-test-cs/Lib.cs b/modules/namespace-test-cs/Lib.cs index 3ae12660e43..cee2b465034 100644 --- a/modules/namespace-test-cs/Lib.cs +++ b/modules/namespace-test-cs/Lib.cs @@ -26,6 +26,24 @@ public partial struct AuthSummary public static partial class Functions { + [Reducer] + public static void AddAuthUser(ReducerContext ctx, uint id) + { + AuthLib.Functions.Add(ctx, id); + Log.Info($"Auth users: {AuthLib.Functions.Count(ctx)}"); + } + + [Procedure] + public static ulong CountAuthUsers(ProcedureContext ctx) => AuthLib.Functions.CountUsers(ctx); + + [HttpHandler] + public static HttpResponse RootAuthCount(HandlerContext ctx, HttpRequest request) => + AuthLib.Functions.AuthCount(ctx, request); + + [HttpRouter] + public static Router Routes() => + Router.New().Get("/root-auth-count", new Handler(nameof(RootAuthCount))); + #pragma warning disable STDB_UNSTABLE [ClientVisibilityFilter] public static readonly Filter ProtectedRows = new Filter.Sql( diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/CountAuthUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/CountAuthUsers.g.cs new file mode 100644 index 00000000000..74eb276e753 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/CountAuthUsers.g.cs @@ -0,0 +1,64 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteProcedures : RemoteBase + { + public void CountAuthUsers(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalCountAuthUsers((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalCountAuthUsers(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.CountAuthUsersArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class CountAuthUsers + { + [DataMember(Name = "Value")] + public ulong Value; + + public CountAuthUsers(ulong Value) + { + this.Value = Value; + } + + public CountAuthUsers() + { + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class CountAuthUsersArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "count_auth_users"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/AddAuthUser.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/AddAuthUser.g.cs new file mode 100644 index 00000000000..5fdfece427a --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Reducers/AddAuthUser.g.cs @@ -0,0 +1,66 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void AddAuthUserHandler(ReducerEventContext ctx, uint id); + public event AddAuthUserHandler? OnAddAuthUser; + + public void AddAuthUser(uint id) + { + conn.InternalCallReducer(new Reducer.AddAuthUser(id)); + } + + public bool InvokeAddAuthUser(ReducerEventContext ctx, Reducer.AddAuthUser args) + { + if (OnAddAuthUser == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnAddAuthUser( + ctx, + args.Id + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class AddAuthUser : Reducer, IReducerArgs + { + [DataMember(Name = "id")] + public uint Id; + + public AddAuthUser(uint Id) + { + this.Id = Id; + } + + public AddAuthUser() + { + } + + string IReducerArgs.ReducerName => "add_auth_user"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs index 6241c5db4b6..26e44ec34e0 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs @@ -663,6 +663,7 @@ protected override bool Dispatch(IReducerEventContext context, Reducer reducer) var eventContext = (ReducerEventContext)context; return reducer switch { + Reducer.AddAuthUser args => Reducers.InvokeAddAuthUser(eventContext, args), Reducer.Exercise args => Reducers.InvokeExercise(eventContext, args), Reducer.WriteProtectedRow args => Reducers.InvokeWriteProtectedRow(eventContext, args), Reducer.Extra args => Reducers.InvokeExtra(eventContext, args), From 1c754ae2896ce27d4eab31901a85fe2a68cdfd70 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Mon, 21 Sep 2026 14:23:01 -0500 Subject: [PATCH 22/49] Resolve namespaces only once --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 25 +- .../snapshots/Module.net10#FFI.verified.cs | 533 +++++++++++------- .../snapshots/Module.net10#FFI.verified.cs | 76 ++- .../snapshots/Module.net10#FFI.verified.cs | 464 +++++++++------ crates/bindings-csharp/Codegen/Module.cs | 26 +- 5 files changed, 723 insertions(+), 401 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 7dde87ea7cf..272a3f3e7d6 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -804,6 +804,7 @@ public static bool CheckNamespaces() [first] = "auth_data", [second] = "audit_data", ["merged"] = "public", + [{{SymbolDisplay.FormatLiteral(moduleAssembly.Identity.ToString(), true)}}] = "cached", }; var registry = new NamespaceRegistry("root", placements); placements[first] = "changed"; @@ -880,7 +881,7 @@ public static bool CheckNamespaces() var first = Activator.CreateInstance(builderType)!; var second = Activator.CreateInstance(builderType)!; var root = builderType.Assembly.GetType("SpacetimeDB.Internal.Module")! - .GetProperty("RootBuilder")!.GetValue(null)!; + .GetField("RootBuilder")!.GetValue(null)!; byte[] Snapshot(object builder) => (byte[])consumerType.GetMethod("Snapshot")! .Invoke(null, [builder])!; var empty = Snapshot(second); @@ -905,6 +906,28 @@ byte[] Snapshot(object builder) => (byte[])consumerType.GetMethod("Snapshot")! Assert.Equal(rootBefore, Snapshot(root)); Assert.True((bool)consumerType.GetMethod("CheckNamespaces")!.Invoke(null, null)!); + + var loadedModule = loadContext.Assemblies.Single(a => a.GetName().Name == moduleAssembly.Name); + var cachedHandles = loadedModule.GetTypes() + .Select(type => (Type: type, Field: type.GetField("__resolvedName", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic))) + .Where(handle => handle.Field is not null).ToArray(); + Assert.NotEmpty(cachedHandles); + foreach (var (type, field) in cachedHandles) + { + Assert.True(field!.IsInitOnly); + Assert.False(type.Attributes.HasFlag(System.Reflection.TypeAttributes.BeforeFieldInit)); + var name = Assert.IsType(field.GetValue(null)); + Assert.StartsWith("cached.", name); + Assert.Same(name, field.GetValue(null)); + } + foreach (var baseName in new[] + { + "UniqueIndex`4", "IndexBase`1", + "ReadOnlyUniqueIndex`4", "ReadOnlyIndexBase`1", + "ReadOnlyTableView`1", + }) + Assert.Contains(cachedHandles, handle => handle.Type.BaseType!.Name == baseName); } finally { diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs index c22232203c8..553f927f37d 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs @@ -2130,13 +2130,17 @@ public sealed class IdentityUniqueIndex SpacetimeDB.Identity.BSATN > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "Player_Identity_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdentityUniqueIndex() { } + internal IdentityUniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "Player_Identity_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -2263,13 +2267,17 @@ public sealed class IdentityFieldUniqueIndex SpacetimeDB.BSATN.String > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestAutoIncNotInteger_IdentityField_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdentityFieldUniqueIndex() { } + internal IdentityFieldUniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestAutoIncNotInteger_IdentityField_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -2550,43 +2558,62 @@ public ulong Clear() => >.DoClear(); public sealed class TestIndexWithoutColumnsIndex() - : SpacetimeDB.Internal.IndexBase( + : SpacetimeDB.Internal.IndexBase(__resolvedName) + { + private static readonly string __resolvedName = global::SpacetimeDB.Internal.Module.ResolveName( "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestIndexIssues__idx_btree" - ) - ) { } + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestIndexWithoutColumnsIndex() { } + } public TestIndexWithoutColumnsIndex TestIndexWithoutColumns => new(); public sealed class TestIndexWithEmptyColumnsIndex() - : SpacetimeDB.Internal.IndexBase( + : SpacetimeDB.Internal.IndexBase(__resolvedName) + { + private static readonly string __resolvedName = global::SpacetimeDB.Internal.Module.ResolveName( "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestIndexIssues__idx_btree" - ) - ) { } + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestIndexWithEmptyColumnsIndex() { } + } public TestIndexWithEmptyColumnsIndex TestIndexWithEmptyColumns => new(); public sealed class TestUnknownColumnsIndex() - : SpacetimeDB.Internal.IndexBase( + : SpacetimeDB.Internal.IndexBase(__resolvedName) + { + private static readonly string __resolvedName = global::SpacetimeDB.Internal.Module.ResolveName( "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestIndexIssues__idx_btree" - ) - ) { } + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestUnknownColumnsIndex() { } + } public TestUnknownColumnsIndex TestUnknownColumns => new(); public sealed class SelfIndexingColumnIndex() - : SpacetimeDB.Internal.IndexBase( + : SpacetimeDB.Internal.IndexBase(__resolvedName) + { + private static readonly string __resolvedName = global::SpacetimeDB.Internal.Module.ResolveName( "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestIndexIssues_SelfIndexingColumn_idx_btree" - ) - ) - { + ); + + // Prevent eager initialization before the root installs namespace placements. + static SelfIndexingColumnIndex() { } + public IEnumerable Filter(int SelfIndexingColumn) => DoFilter( new SpacetimeDB.Internal.BTreeIndexBounds( @@ -2621,13 +2648,17 @@ public ulong Delete(global::SpacetimeDB.Bound SelfIndexingColumn) => public SelfIndexingColumnIndex SelfIndexingColumn => new(); public sealed class SecondaryIndexingColumnIndex() - : SpacetimeDB.Internal.IndexBase( + : SpacetimeDB.Internal.IndexBase(__resolvedName) + { + private static readonly string __resolvedName = global::SpacetimeDB.Internal.Module.ResolveName( "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestIndexIssues_SecondaryIndexingColumn_idx_btree" - ) - ) - { + ); + + // Prevent eager initialization before the root installs namespace placements. + static SecondaryIndexingColumnIndex() { } + public IEnumerable Filter(int SecondaryIndexingColumn) => DoFilter( new SpacetimeDB.Internal.BTreeIndexBounds( @@ -2662,13 +2693,17 @@ public ulong Delete(global::SpacetimeDB.Bound SecondaryIndexingColumn) => public SecondaryIndexingColumnIndex SecondaryIndexingColumn => new(); public sealed class TestUnexpectedColumnsIndex() - : SpacetimeDB.Internal.IndexBase( + : SpacetimeDB.Internal.IndexBase(__resolvedName) + { + private static readonly string __resolvedName = global::SpacetimeDB.Internal.Module.ResolveName( "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestIndexIssues_SelfIndexingColumn_idx_btree" - ) - ) - { + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestUnexpectedColumnsIndex() { } + public IEnumerable Filter(int SelfIndexingColumn) => DoFilter( new SpacetimeDB.Internal.BTreeIndexBounds( @@ -2955,13 +2990,17 @@ public sealed class IdCorrectTypeUniqueIndex SpacetimeDB.BSATN.I32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutScheduleAt_IdCorrectType_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdCorrectTypeUniqueIndex() { } + internal IdCorrectTypeUniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithoutScheduleAt_IdCorrectType_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -3075,13 +3114,17 @@ public sealed class IdWrongTypeUniqueIndex SpacetimeDB.BSATN.String > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongPrimaryKeyType_IdWrongType_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdWrongTypeUniqueIndex() { } + internal IdWrongTypeUniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithWrongPrimaryKeyType_IdWrongType_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -3195,13 +3238,17 @@ public sealed class IdCorrectTypeUniqueIndex SpacetimeDB.BSATN.I32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongScheduleAtType_IdCorrectType_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdCorrectTypeUniqueIndex() { } + internal IdCorrectTypeUniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithWrongScheduleAtType_IdCorrectType_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -3320,13 +3367,17 @@ public sealed class PrimaryKeyFieldUniqueIndex SpacetimeDB.BSATN.Enum > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestUniqueNotEquatable_PrimaryKeyField_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static PrimaryKeyFieldUniqueIndex() { } + internal PrimaryKeyFieldUniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestUniqueNotEquatable_PrimaryKeyField_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -4077,13 +4128,17 @@ namespace SpacetimeDB.Generated.diag_4F830E2879BB50E3.ViewHandles public sealed class PlayerReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "Player" + ); + + // Prevent eager initialization before the root installs namespace placements. + static PlayerReadOnly() { } + internal PlayerReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "Player" - ) - ) { } + : base(__resolvedName) { } ///

/// Returns the number of rows in this table. @@ -4101,13 +4156,17 @@ public sealed class IdentityIndex SpacetimeDB.Identity.BSATN > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "Player_Identity_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdentityIndex() { } + internal IdentityIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "Player_Identity_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::Player? Find(SpacetimeDB.Identity key) => FindSingle(key); } @@ -4118,13 +4177,17 @@ internal IdentityIndex() public sealed class TestAutoIncNotIntegerReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestAutoIncNotInteger" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestAutoIncNotIntegerReadOnly() { } + internal TestAutoIncNotIntegerReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestAutoIncNotInteger" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -4142,13 +4205,17 @@ public sealed class IdentityFieldIndex SpacetimeDB.BSATN.String > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestAutoIncNotInteger_IdentityField_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdentityFieldIndex() { } + internal IdentityFieldIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestAutoIncNotInteger_IdentityField_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::TestAutoIncNotInteger? Find(string key) => FindSingle(key); } @@ -4159,13 +4226,17 @@ internal IdentityFieldIndex() public sealed class TestDefaultFieldValuesReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDefaultFieldValues" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestDefaultFieldValuesReadOnly() { } + internal TestDefaultFieldValuesReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestDefaultFieldValues" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -4179,13 +4250,17 @@ internal TestDefaultFieldValuesReadOnly() public sealed class TestDuplicateTableNameReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDuplicateTableName" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestDuplicateTableNameReadOnly() { } + internal TestDuplicateTableNameReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestDuplicateTableName" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -4199,13 +4274,17 @@ internal TestDuplicateTableNameReadOnly() public sealed class TestIndexIssuesReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestIndexIssuesReadOnly() { } + internal TestIndexIssuesReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestIndexIssues" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -4218,13 +4297,17 @@ internal TestIndexIssuesReadOnly() public sealed class TestIndexWithoutColumnsIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues__idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestIndexWithoutColumnsIndex() { } + internal TestIndexWithoutColumnsIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestIndexIssues__idx_btree" - ) - ) { } + : base(__resolvedName) { } } public TestIndexWithoutColumnsIndex TestIndexWithoutColumns => new(); @@ -4232,13 +4315,17 @@ internal TestIndexWithoutColumnsIndex() public sealed class TestIndexWithEmptyColumnsIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues__idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestIndexWithEmptyColumnsIndex() { } + internal TestIndexWithEmptyColumnsIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestIndexIssues__idx_btree" - ) - ) { } + : base(__resolvedName) { } } public TestIndexWithEmptyColumnsIndex TestIndexWithEmptyColumns => new(); @@ -4246,13 +4333,17 @@ internal TestIndexWithEmptyColumnsIndex() public sealed class TestUnknownColumnsIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues__idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestUnknownColumnsIndex() { } + internal TestUnknownColumnsIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestIndexIssues__idx_btree" - ) - ) { } + : base(__resolvedName) { } } public TestUnknownColumnsIndex TestUnknownColumns => new(); @@ -4260,13 +4351,17 @@ internal TestUnknownColumnsIndex() public sealed class SelfIndexingColumnIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues_SelfIndexingColumn_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static SelfIndexingColumnIndex() { } + internal SelfIndexingColumnIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestIndexIssues_SelfIndexingColumn_idx_btree" - ) - ) { } + : base(__resolvedName) { } public IEnumerable Filter(int SelfIndexingColumn) => DoFilter( @@ -4290,13 +4385,17 @@ internal SelfIndexingColumnIndex() public sealed class SecondaryIndexingColumnIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues_SecondaryIndexingColumn_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static SecondaryIndexingColumnIndex() { } + internal SecondaryIndexingColumnIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestIndexIssues_SecondaryIndexingColumn_idx_btree" - ) - ) { } + : base(__resolvedName) { } public IEnumerable Filter(int SecondaryIndexingColumn) => DoFilter( @@ -4320,13 +4419,17 @@ internal SecondaryIndexingColumnIndex() public sealed class TestUnexpectedColumnsIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues_SelfIndexingColumn_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestUnexpectedColumnsIndex() { } + internal TestUnexpectedColumnsIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestIndexIssues_SelfIndexingColumn_idx_btree" - ) - ) { } + : base(__resolvedName) { } public IEnumerable Filter(int SelfIndexingColumn) => DoFilter( @@ -4351,13 +4454,17 @@ internal TestUnexpectedColumnsIndex() public sealed class TestScheduleWithMissingScheduleAtFieldReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithMissingScheduleAtField" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithMissingScheduleAtFieldReadOnly() { } + internal TestScheduleWithMissingScheduleAtFieldReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithMissingScheduleAtField" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -4371,13 +4478,17 @@ internal TestScheduleWithMissingScheduleAtFieldReadOnly() public sealed class TestScheduleWithoutPrimaryKeyReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutPrimaryKey" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithoutPrimaryKeyReadOnly() { } + internal TestScheduleWithoutPrimaryKeyReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithoutPrimaryKey" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -4391,13 +4502,17 @@ internal TestScheduleWithoutPrimaryKeyReadOnly() public sealed class TestScheduleWithoutScheduleAtReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutScheduleAt" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithoutScheduleAtReadOnly() { } + internal TestScheduleWithoutScheduleAtReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithoutScheduleAt" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -4415,13 +4530,17 @@ public sealed class IdCorrectTypeIndex SpacetimeDB.BSATN.I32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutScheduleAt_IdCorrectType_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdCorrectTypeIndex() { } + internal IdCorrectTypeIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithoutScheduleAt_IdCorrectType_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::TestScheduleIssues? Find(int key) => FindSingle(key); } @@ -4432,13 +4551,17 @@ internal IdCorrectTypeIndex() public sealed class TestScheduleWithWrongPrimaryKeyTypeReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongPrimaryKeyType" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithWrongPrimaryKeyTypeReadOnly() { } + internal TestScheduleWithWrongPrimaryKeyTypeReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithWrongPrimaryKeyType" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -4456,13 +4579,17 @@ public sealed class IdWrongTypeIndex SpacetimeDB.BSATN.String > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongPrimaryKeyType_IdWrongType_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdWrongTypeIndex() { } + internal IdWrongTypeIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithWrongPrimaryKeyType_IdWrongType_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::TestScheduleIssues? Find(string key) => FindSingle(key); } @@ -4473,13 +4600,17 @@ internal IdWrongTypeIndex() public sealed class TestScheduleWithWrongScheduleAtTypeReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongScheduleAtType" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithWrongScheduleAtTypeReadOnly() { } + internal TestScheduleWithWrongScheduleAtTypeReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithWrongScheduleAtType" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -4497,13 +4628,17 @@ public sealed class IdCorrectTypeIndex SpacetimeDB.BSATN.I32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongScheduleAtType_IdCorrectType_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdCorrectTypeIndex() { } + internal IdCorrectTypeIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithWrongScheduleAtType_IdCorrectType_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::TestScheduleIssues? Find(int key) => FindSingle(key); } @@ -4514,13 +4649,17 @@ internal IdCorrectTypeIndex() public sealed class TestUniqueNotEquatableReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestUniqueNotEquatable" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestUniqueNotEquatableReadOnly() { } + internal TestUniqueNotEquatableReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestUniqueNotEquatable" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -4538,13 +4677,17 @@ public sealed class PrimaryKeyFieldIndex SpacetimeDB.BSATN.Enum > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestUniqueNotEquatable_PrimaryKeyField_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static PrimaryKeyFieldIndex() { } + internal PrimaryKeyFieldIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestUniqueNotEquatable_PrimaryKeyField_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::TestUniqueNotEquatable? Find(TestEnumWithExplicitValues key) => FindSingle(key); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs index baec61ee65b..47f15612452 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs @@ -603,13 +603,17 @@ public sealed class IdUniqueIndex SpacetimeDB.BSATN.I32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable_Id_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdUniqueIndex() { } + internal IdUniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "DemoTable_Id_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -622,13 +626,17 @@ internal IdUniqueIndex() public IdUniqueIndex Id => new(); public sealed class ByIdIndex() - : SpacetimeDB.Internal.IndexBase( + : SpacetimeDB.Internal.IndexBase(__resolvedName) + { + private static readonly string __resolvedName = global::SpacetimeDB.Internal.Module.ResolveName( "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "DemoTable_Id_idx_btree" - ) - ) - { + ); + + // Prevent eager initialization before the root installs namespace placements. + static ByIdIndex() { } + public IEnumerable Filter(int Id) => DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(Id)); @@ -693,13 +701,17 @@ namespace SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.ViewHandles public sealed class DemoTableReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable" + ); + + // Prevent eager initialization before the root installs namespace placements. + static DemoTableReadOnly() { } + internal DemoTableReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "DemoTable" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -717,13 +729,17 @@ public sealed class IdIndex SpacetimeDB.BSATN.I32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable_Id_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdIndex() { } + internal IdIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "DemoTable_Id_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::DemoTable? Find(int key) => FindSingle(key); } @@ -733,13 +749,17 @@ internal IdIndex() public sealed class ByIdIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable_Id_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static ByIdIndex() { } + internal ByIdIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "DemoTable_Id_idx_btree" - ) - ) { } + : base(__resolvedName) { } public IEnumerable Filter(int Id) => DoFilter( diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs index 07336d4dbfd..141faa88f64 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs @@ -1706,13 +1706,17 @@ public ulong Clear() => >.DoClear(); internal sealed class LocationIndex() - : SpacetimeDB.Internal.IndexBase( + : SpacetimeDB.Internal.IndexBase(__resolvedName) + { + private static readonly string __resolvedName = global::SpacetimeDB.Internal.Module.ResolveName( "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "BTreeMultiColumn_X_Y_Z_idx_btree" - ) - ) - { + ); + + // Prevent eager initialization before the root installs namespace placements. + static LocationIndex() { } + public IEnumerable Filter(uint X) => DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(X)); @@ -1911,13 +1915,17 @@ internal sealed class IdUniqueIndex SpacetimeDB.Identity.BSATN > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews_Id_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdUniqueIndex() { } + internal IdUniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "BTreeViews_Id_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -1930,13 +1938,17 @@ internal IdUniqueIndex() internal IdUniqueIndex Id => new(); internal sealed class LocationIndex() - : SpacetimeDB.Internal.IndexBase( + : SpacetimeDB.Internal.IndexBase(__resolvedName) + { + private static readonly string __resolvedName = global::SpacetimeDB.Internal.Module.ResolveName( "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "BTreeViews_X_Y_idx_btree" - ) - ) - { + ); + + // Prevent eager initialization before the root installs namespace placements. + static LocationIndex() { } + public IEnumerable Filter(uint X) => DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(X)); @@ -1995,13 +2007,17 @@ public ulong Delete((uint X, global::SpacetimeDB.Bound Y) f) => internal LocationIndex Location => new(); internal sealed class FactionIndex() - : SpacetimeDB.Internal.IndexBase( + : SpacetimeDB.Internal.IndexBase(__resolvedName) + { + private static readonly string __resolvedName = global::SpacetimeDB.Internal.Module.ResolveName( "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "BTreeViews_Faction_idx_btree" - ) - ) - { + ); + + // Prevent eager initialization before the root installs namespace placements. + static FactionIndex() { } + public IEnumerable Filter(string Faction) => DoFilter( new SpacetimeDB.Internal.BTreeIndexBounds( @@ -2133,13 +2149,17 @@ public sealed class FooUniqueIndex SpacetimeDB.BSATN.U32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1_Foo_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static FooUniqueIndex() { } + internal FooUniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "MultiTable1_Foo_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -2152,13 +2172,17 @@ internal FooUniqueIndex() public FooUniqueIndex Foo => new(); public sealed class NameIndex() - : SpacetimeDB.Internal.IndexBase( + : SpacetimeDB.Internal.IndexBase(__resolvedName) + { + private static readonly string __resolvedName = global::SpacetimeDB.Internal.Module.ResolveName( "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "MultiTable1_Name_idx_btree" - ) - ) - { + ); + + // Prevent eager initialization before the root installs namespace placements. + static NameIndex() { } + public IEnumerable Filter(string Name) => DoFilter( new SpacetimeDB.Internal.BTreeIndexBounds( @@ -2285,13 +2309,17 @@ public sealed class BarUniqueIndex SpacetimeDB.BSATN.U32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable2_Bar_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static BarUniqueIndex() { } + internal BarUniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "MultiTable2_Bar_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -2452,13 +2480,17 @@ public sealed class IdUniqueIndex SpacetimeDB.BSATN.I32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PublicTable_Id_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdUniqueIndex() { } + internal IdUniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "PublicTable_Id_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -2580,13 +2612,17 @@ internal sealed class Unique1UniqueIndex SpacetimeDB.BSATN.U32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName_Unique1_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static Unique1UniqueIndex() { } + internal Unique1UniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "RegressionMultipleUniqueIndexesHadSameName_Unique1_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -2605,13 +2641,17 @@ internal sealed class Unique2UniqueIndex SpacetimeDB.BSATN.U32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName_Unique2_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static Unique2UniqueIndex() { } + internal Unique2UniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "RegressionMultipleUniqueIndexesHadSameName_Unique2_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -2730,13 +2770,17 @@ public sealed class ScheduledIdUniqueIndex SpacetimeDB.BSATN.U64 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "SendMessageTimer_ScheduledId_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static ScheduledIdUniqueIndex() { } + internal ScheduledIdUniqueIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "SendMessageTimer_ScheduledId_idx_btree" - ) - ) { } + : base(__resolvedName) { } // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based @@ -2892,13 +2936,17 @@ namespace SpacetimeDB.Generated.server_D513E4815F57969C.ViewHandles internal sealed class BTreeMultiColumnReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeMultiColumn" + ); + + // Prevent eager initialization before the root installs namespace placements. + static BTreeMultiColumnReadOnly() { } + internal BTreeMultiColumnReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "BTreeMultiColumn" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -2911,13 +2959,17 @@ internal BTreeMultiColumnReadOnly() public sealed class LocationIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeMultiColumn_X_Y_Z_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static LocationIndex() { } + internal LocationIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "BTreeMultiColumn_X_Y_Z_idx_btree" - ) - ) { } + : base(__resolvedName) { } public IEnumerable Filter(uint X) => DoFilter( @@ -2990,13 +3042,17 @@ internal LocationIndex() internal sealed class BTreeViewsReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews" + ); + + // Prevent eager initialization before the root installs namespace placements. + static BTreeViewsReadOnly() { } + internal BTreeViewsReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "BTreeViews" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -3014,13 +3070,17 @@ public sealed class IdIndex SpacetimeDB.Identity.BSATN > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews_Id_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdIndex() { } + internal IdIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "BTreeViews_Id_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::BTreeViews? Find(SpacetimeDB.Identity key) => FindSingle(key); } @@ -3030,13 +3090,17 @@ internal IdIndex() public sealed class LocationIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews_X_Y_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static LocationIndex() { } + internal LocationIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "BTreeViews_X_Y_idx_btree" - ) - ) { } + : base(__resolvedName) { } public IEnumerable Filter(uint X) => DoFilter( @@ -3080,13 +3144,17 @@ internal LocationIndex() public sealed class FactionIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews_Faction_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static FactionIndex() { } + internal FactionIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "BTreeViews_Faction_idx_btree" - ) - ) { } + : base(__resolvedName) { } public IEnumerable Filter(string Faction) => DoFilter( @@ -3113,13 +3181,17 @@ internal FactionIndex() public sealed class MultiTable1ReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1" + ); + + // Prevent eager initialization before the root installs namespace placements. + static MultiTable1ReadOnly() { } + internal MultiTable1ReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "MultiTable1" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -3137,13 +3209,17 @@ public sealed class FooIndex SpacetimeDB.BSATN.U32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1_Foo_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static FooIndex() { } + internal FooIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "MultiTable1_Foo_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::MultiTableRow? Find(uint key) => FindSingle(key); } @@ -3153,13 +3229,17 @@ internal FooIndex() public sealed class NameIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1_Name_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static NameIndex() { } + internal NameIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "MultiTable1_Name_idx_btree" - ) - ) { } + : base(__resolvedName) { } public IEnumerable Filter(string Name) => DoFilter( @@ -3186,13 +3266,17 @@ internal NameIndex() public sealed class MultiTable2ReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable2" + ); + + // Prevent eager initialization before the root installs namespace placements. + static MultiTable2ReadOnly() { } + internal MultiTable2ReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "MultiTable2" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -3210,13 +3294,17 @@ public sealed class BarIndex SpacetimeDB.BSATN.U32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable2_Bar_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static BarIndex() { } + internal BarIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "MultiTable2_Bar_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::MultiTableRow? Find(uint key) => FindSingle(key); } @@ -3227,13 +3315,17 @@ internal BarIndex() public sealed class PrivateTableReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PrivateTable" + ); + + // Prevent eager initialization before the root installs namespace placements. + static PrivateTableReadOnly() { } + internal PrivateTableReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "PrivateTable" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -3247,13 +3339,17 @@ internal PrivateTableReadOnly() public sealed class PublicTableReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PublicTable" + ); + + // Prevent eager initialization before the root installs namespace placements. + static PublicTableReadOnly() { } + internal PublicTableReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "PublicTable" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -3271,13 +3367,17 @@ public sealed class IdIndex SpacetimeDB.BSATN.I32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PublicTable_Id_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static IdIndex() { } + internal IdIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "PublicTable_Id_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::PublicTable? Find(int key) => FindSingle(key); } @@ -3288,13 +3388,17 @@ internal IdIndex() internal sealed class RegressionMultipleUniqueIndexesHadSameNameReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName" + ); + + // Prevent eager initialization before the root installs namespace placements. + static RegressionMultipleUniqueIndexesHadSameNameReadOnly() { } + internal RegressionMultipleUniqueIndexesHadSameNameReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "RegressionMultipleUniqueIndexesHadSameName" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -3312,13 +3416,17 @@ public sealed class Unique1Index SpacetimeDB.BSATN.U32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName_Unique1_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static Unique1Index() { } + internal Unique1Index() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "RegressionMultipleUniqueIndexesHadSameName_Unique1_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::RegressionMultipleUniqueIndexesHadSameName? Find(uint key) => FindSingle(key); @@ -3334,13 +3442,17 @@ public sealed class Unique2Index SpacetimeDB.BSATN.U32 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName_Unique2_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static Unique2Index() { } + internal Unique2Index() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "RegressionMultipleUniqueIndexesHadSameName_Unique2_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::RegressionMultipleUniqueIndexesHadSameName? Find(uint key) => FindSingle(key); @@ -3352,13 +3464,17 @@ internal Unique2Index() public sealed class SendMessageTimerReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "SendMessageTimer" + ); + + // Prevent eager initialization before the root installs namespace placements. + static SendMessageTimerReadOnly() { } + internal SendMessageTimerReadOnly() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "SendMessageTimer" - ) - ) { } + : base(__resolvedName) { } /// /// Returns the number of rows in this table. @@ -3376,13 +3492,17 @@ public sealed class ScheduledIdIndex SpacetimeDB.BSATN.U64 > { + private static readonly string __resolvedName = + global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "SendMessageTimer_ScheduledId_idx_btree" + ); + + // Prevent eager initialization before the root installs namespace placements. + static ScheduledIdIndex() { } + internal ScheduledIdIndex() - : base( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "SendMessageTimer_ScheduledId_idx_btree" - ) - ) { } + : base(__resolvedName) { } public global::Timers.SendMessageTimer? Find(ulong key) => FindSingle(key); } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 5621c6f7a8b..4f041d31e88 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -504,6 +504,17 @@ private string LookupName(string localName) => sharedContexts ? $"global::SpacetimeDB.Internal.Module.ResolveName({SymbolDisplay.FormatLiteral(assemblyIdentity, true)}, {SymbolDisplay.FormatLiteral(localName, true)})" : SymbolDisplay.FormatLiteral(localName, true); + private string HandleLookupName(string localName) => + sharedContexts ? "__resolvedName" : LookupName(localName); + + private string HandleLookupNameCache(string typeName, string localName) => sharedContexts + ? $$""" + private static readonly string __resolvedName = {{LookupName(localName)}}; + // Prevent eager initialization before the root installs namespace placements. + static {{typeName}}() { } + """ + : ""; + public int? GetColumnIndex(AttributeData attrContext, string name, DiagReporter diag) { var index = Members @@ -599,7 +610,8 @@ public IEnumerable GenerateTableAccessorFilters(TableAccessor tableAcces : ""; yield return $$""" {{vis}} sealed class {{f.Identifier}}UniqueIndex : {{uniqueIndexBase}}<{{tableAccessor.Identifier}}, {{globalName}}, {{f.Type.Name}}, {{f.Type.BSATNName}}> { - internal {{f.Identifier}}UniqueIndex() : base({{LookupName(standardIndexName)}}) {} + {{HandleLookupNameCache(f.Identifier + "UniqueIndex", standardIndexName)}} + internal {{f.Identifier}}UniqueIndex() : base({{HandleLookupName(standardIndexName)}}) {} // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. @@ -626,7 +638,8 @@ public IEnumerable GenerateTableAccessorFilters(TableAccessor tableAcces var standardIndexName = index.StandardIndexName(tableAccessor); yield return $$""" - {{vis}} sealed class {{identifierName}}Index() : SpacetimeDB.Internal.IndexBase<{{globalName}}>({{LookupName(standardIndexName)}}) { + {{vis}} sealed class {{identifierName}}Index() : SpacetimeDB.Internal.IndexBase<{{globalName}}>({{HandleLookupName(standardIndexName)}}) { + {{HandleLookupNameCache(identifierName + "Index", standardIndexName)}} """; for (var n = 0; n < members.Length; n++) @@ -700,7 +713,8 @@ public sealed class {{{f.Identifier}}}Index {{{f.Type.Name}}}, {{{f.Type.BSATNName}}}> { - internal {{{f.Identifier}}}Index() : base({{{LookupName(standardIndexName)}}}) { } + {{{HandleLookupNameCache(f.Identifier + "Index", standardIndexName)}}} + internal {{{f.Identifier}}}Index() : base({{{HandleLookupName(standardIndexName)}}}) { } public {{{globalName}}}? Find({{{f.Type.Name}}} key) => FindSingle(key); } @@ -727,7 +741,8 @@ public sealed class {{{f.Identifier}}}Index public sealed class {{{identifierName}}}Index : global::SpacetimeDB.Internal.ReadOnlyIndexBase<{{{globalName}}}> { - internal {{{identifierName}}}Index() : base({{{LookupName(standardIndexName)}}}) {} + {{{HandleLookupNameCache(identifierName + "Index", standardIndexName)}}} + internal {{{identifierName}}}Index() : base({{{HandleLookupName(standardIndexName)}}}) {} """, }; @@ -908,7 +923,8 @@ public IEnumerable GenerateReadOnlyAccessors() {{{visibility}}} sealed class {{{accessorIdentifier}}}ReadOnly : global::SpacetimeDB.Internal.ReadOnlyTableView<{{{globalName}}}> { - internal {{{accessorIdentifier}}}ReadOnly() : base({{{LookupName(accessor.Name)}}}) { } + {{{HandleLookupNameCache(accessorIdentifier + "ReadOnly", accessor.Name)}}} + internal {{{accessorIdentifier}}}ReadOnly() : base({{{HandleLookupName(accessor.Name)}}}) { } /// /// Returns the number of rows in this table. From 3f7c582bc689c1e275b37dbf46407873a5ad5649 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Mon, 21 Sep 2026 14:42:52 -0500 Subject: [PATCH 23/49] Resolve namespaces only once in module queries --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 32 +++ .../ExtraCompilationErrors.net10.verified.txt | 178 +++++++-------- .../diag/snapshots/Module#FFI.verified.cs | 204 +++++++++++++----- .../snapshots/Module.net10#FFI.verified.cs | 204 +++++++++++++----- .../snapshots/Module#FFI.verified.cs | 17 +- .../snapshots/Module.net10#FFI.verified.cs | 17 +- .../server/snapshots/Module#FFI.verified.cs | 136 +++++++++--- .../snapshots/Module.net10#FFI.verified.cs | 136 +++++++++--- crates/bindings-csharp/Codegen/Module.cs | 10 +- 9 files changed, 676 insertions(+), 258 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 272a3f3e7d6..3e17309300b 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -928,6 +928,38 @@ byte[] Snapshot(object builder) => (byte[])consumerType.GetMethod("Snapshot")! "ReadOnlyTableView`1", }) Assert.Contains(cachedHandles, handle => handle.Type.BaseType!.Name == baseName); + + var queriesType = loadedModule.GetTypes().Single(type => + type.Name == "Queries" && type.DeclaringType?.Name == "AssemblyDescriptor"); + var queries = Activator.CreateInstance(queriesType); + var factories = queriesType.GetMethods(System.Reflection.BindingFlags.Instance + | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic + | System.Reflection.BindingFlags.DeclaredOnly); + Assert.NotEmpty(factories); + var sqlNames = new List(); + foreach (var factory in factories) + { + var cache = queriesType.DeclaringType!.GetNestedType(factory.Name + "SqlNameCache", + System.Reflection.BindingFlags.NonPublic)!; + Assert.False(cache.Attributes.HasFlag(System.Reflection.TypeAttributes.BeforeFieldInit)); + var field = cache.GetField("Name", System.Reflection.BindingFlags.Static + | System.Reflection.BindingFlags.NonPublic)!; + Assert.True(field.IsInitOnly); + var cachedName = field.GetValue(null)!; + var segments = field.FieldType.GetProperty("NamespaceSegments")!; + var firstQuery = factory.Invoke(queries, null)!; + var secondQuery = factory.Invoke(queries, null)!; + Assert.NotSame(firstQuery, secondQuery); + var nameField = factory.ReturnType.GetFields(System.Reflection.BindingFlags.Instance + | System.Reflection.BindingFlags.NonPublic).Single(f => f.FieldType == field.FieldType); + Assert.Same(segments.GetValue(cachedName), segments.GetValue(nameField.GetValue(firstQuery))); + Assert.Same(segments.GetValue(cachedName), segments.GetValue(nameField.GetValue(secondQuery))); + Assert.Equal("SELECT * FROM " + cachedName, + factory.ReturnType.GetMethod("ToSql")!.Invoke(firstQuery, null)); + Assert.StartsWith("\"cached\".", cachedName.ToString()); + sqlNames.Add(cachedName.ToString()!); + } + Assert.Equal(factories.Length, sqlNames.Distinct().Count()); } finally { diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt index faa165e7d56..d528135ba94 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt @@ -252,6 +252,52 @@ public partial struct TestDefaultFieldValues ] } }, + {/* + { + var tableName = TestDuplicateTableNameSqlNameCache.Name; + ^^^^ + return new(tableName, new TestDuplicateTableNameCols(tableName), new TestDuplicateTableNameIxCols(tableName)); +*/ + Message: Ambiguity between 'AssemblyDescriptor.TestDuplicateTableNameSqlNameCache.Name' and 'AssemblyDescriptor.TestDuplicateTableNameSqlNameCache.Name', + Severity: Error, + Descriptor: { + Id: CS0229, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0229), + MessageFormat: Ambiguity between '{0}' and '{1}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, + {/* + { + var tableName = TestDuplicateTableNameSqlNameCache.Name; + ^^^^ + return new(tableName, new TestDuplicateTableNameCols(tableName), new TestDuplicateTableNameIxCols(tableName)); +*/ + Message: Ambiguity between 'AssemblyDescriptor.TestDuplicateTableNameSqlNameCache.Name' and 'AssemblyDescriptor.TestDuplicateTableNameSqlNameCache.Name', + Severity: Error, + Descriptor: { + Id: CS0229, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0229), + MessageFormat: Ambiguity between '{0}' and '{1}', + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, {/* var returnValue = Module.ViewDefWrongContext((SpacetimeDB.ViewContext)ctx); @@ -350,7 +396,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(800)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(990)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(808)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1030)]', Severity: Error, Descriptor: { Id: CS0121, @@ -373,53 +419,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(800)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(990)]', - Severity: Error, - Descriptor: { - Id: CS0121, - Title: , - HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0121), - MessageFormat: The call is ambiguous between the following methods or properties: '{0}' and '{1}', - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true, - CustomTags: [ - Compiler, - Telemetry, - NotConfigurable - ] - } - }, - {/* - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName("diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestDuplicateTableName"); - return new(tableName, new TestDuplicateTableNameCols(tableName), new TestDuplicateTableNameIxCols(tableName)); - ^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(780)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(970)]', - Severity: Error, - Descriptor: { - Id: CS0121, - Title: , - HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0121), - MessageFormat: The call is ambiguous between the following methods or properties: '{0}' and '{1}', - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true, - CustomTags: [ - Compiler, - Telemetry, - NotConfigurable - ] - } - }, - {/* - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName("diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestDuplicateTableName"); - return new(tableName, new TestDuplicateTableNameCols(tableName), new TestDuplicateTableNameIxCols(tableName)); - ^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(780)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameCols.TestDuplicateTableNameCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(970)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(808)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1030)]', Severity: Error, Descriptor: { Id: CS0121, @@ -437,41 +437,18 @@ public partial struct TestDefaultFieldValues } }, {/* - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName("diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestDuplicateTableName"); - return new(tableName, new TestDuplicateTableNameCols(tableName), new TestDuplicateTableNameIxCols(tableName)); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } -*/ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(790)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(980)]', - Severity: Error, - Descriptor: { - Id: CS0121, - Title: , - HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0121), - MessageFormat: The call is ambiguous between the following methods or properties: '{0}' and '{1}', - Category: Compiler, - DefaultSeverity: Error, - IsEnabledByDefault: true, - CustomTags: [ - Compiler, - Telemetry, - NotConfigurable - ] } - }, - {/* - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName("diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "TestDuplicateTableName"); - return new(tableName, new TestDuplicateTableNameCols(tableName), new TestDuplicateTableNameIxCols(tableName)); - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - } + public readonly struct TestDuplicateTableNameCols + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + { */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(790)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.TestDuplicateTableNameIxCols.TestDuplicateTableNameIxCols(SpacetimeDB.SqlTableName) [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(980)]', + Message: The namespace 'SpacetimeDB.Generated.diag_4F830E2879BB50E3' already contains a definition for 'TestDuplicateTableNameCols', Severity: Error, Descriptor: { - Id: CS0121, + Id: CS0101, Title: , - HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0121), - MessageFormat: The call is ambiguous between the following methods or properties: '{0}' and '{1}', + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0101), + MessageFormat: The namespace '{1}' already contains a definition for '{0}', Category: Compiler, DefaultSeverity: Error, IsEnabledByDefault: true, @@ -483,12 +460,12 @@ public partial struct TestDefaultFieldValues } }, {/* - } - public readonly struct TestDuplicateTableNameCols - ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + public readonly struct TestDuplicateTableNameIxCols + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ { */ - Message: The namespace 'SpacetimeDB.Generated.diag_4F830E2879BB50E3' already contains a definition for 'TestDuplicateTableNameCols', + Message: The namespace 'SpacetimeDB.Generated.diag_4F830E2879BB50E3' already contains a definition for 'TestDuplicateTableNameIxCols', Severity: Error, Descriptor: { Id: CS0101, @@ -506,18 +483,18 @@ public partial struct TestDefaultFieldValues } }, {/* - - public readonly struct TestDuplicateTableNameIxCols - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ { + private static class TestDuplicateTableNameSqlNameCache + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + { */ - Message: The namespace 'SpacetimeDB.Generated.diag_4F830E2879BB50E3' already contains a definition for 'TestDuplicateTableNameIxCols', + Message: The type 'AssemblyDescriptor' already contains a definition for 'TestDuplicateTableNameSqlNameCache', Severity: Error, Descriptor: { - Id: CS0101, + Id: CS0102, Title: , - HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0101), - MessageFormat: The namespace '{1}' already contains a definition for '{0}', + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0102), + MessageFormat: The type '{0}' already contains a definition for '{1}', Category: Compiler, DefaultSeverity: Error, IsEnabledByDefault: true, @@ -643,6 +620,29 @@ public partial struct TestDefaultFieldValues ] } }, + {/* + // Prevent eager initialization before the root installs namespace placements. + static TestDuplicateTableNameSqlNameCache() { } + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + } +*/ + Message: Type 'AssemblyDescriptor.TestDuplicateTableNameSqlNameCache' already defines a member called 'TestDuplicateTableNameSqlNameCache' with the same parameter types, + Severity: Error, + Descriptor: { + Id: CS0111, + Title: , + HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS0111), + MessageFormat: Type '{1}' already defines a member called '{0}' with the same parameter types, + Category: Compiler, + DefaultSeverity: Error, + IsEnabledByDefault: true, + CustomTags: [ + Compiler, + Telemetry, + NotConfigurable + ] + } + }, {/* { public global::SpacetimeDB.Table TestDuplicateTableName() => new AssemblyDescriptor.Queries().TestDuplicateTableName(); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs index 1d7b6d52807..aaa98bc2f1a 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs @@ -1168,6 +1168,18 @@ internal TestDuplicateTableNameIxCols(global::SpacetimeDB.SqlTableName tableName public static partial class AssemblyDescriptor { + private static class TestDuplicateTableNameSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDuplicateTableName" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestDuplicateTableNameSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1176,10 +1188,7 @@ public readonly partial struct Queries TestDuplicateTableNameIxCols > TestDuplicateTableName() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestDuplicateTableName" - ); + var tableName = TestDuplicateTableNameSqlNameCache.Name; return new( tableName, new TestDuplicateTableNameCols(tableName), @@ -1221,14 +1230,23 @@ internal PlayerIxCols(global::SpacetimeDB.SqlTableName tableName) { } public static partial class AssemblyDescriptor { - public readonly partial struct Queries + private static class PlayerSqlNameCache { - public global::SpacetimeDB.Table Player() - { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Player" ); + + // Prevent eager initialization before the root installs namespace placements. + static PlayerSqlNameCache() { } + } + + public readonly partial struct Queries + { + public global::SpacetimeDB.Table Player() + { + var tableName = PlayerSqlNameCache.Name; return new(tableName, new PlayerCols(tableName), new PlayerIxCols(tableName)); } } @@ -1271,6 +1289,18 @@ internal TestAutoIncNotIntegerIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class TestAutoIncNotIntegerSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestAutoIncNotInteger" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestAutoIncNotIntegerSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1279,10 +1309,7 @@ public readonly partial struct Queries TestAutoIncNotIntegerIxCols > TestAutoIncNotInteger() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestAutoIncNotInteger" - ); + var tableName = TestAutoIncNotIntegerSqlNameCache.Name; return new( tableName, new TestAutoIncNotIntegerCols(tableName), @@ -1410,6 +1437,18 @@ internal TestDefaultFieldValuesIxCols(global::SpacetimeDB.SqlTableName tableName public static partial class AssemblyDescriptor { + private static class TestDefaultFieldValuesSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDefaultFieldValues" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestDefaultFieldValuesSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1418,10 +1457,7 @@ public readonly partial struct Queries TestDefaultFieldValuesIxCols > TestDefaultFieldValues() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestDefaultFieldValues" - ); + var tableName = TestDefaultFieldValuesSqlNameCache.Name; return new( tableName, new TestDefaultFieldValuesCols(tableName), @@ -1455,6 +1491,18 @@ internal TestDuplicateTableNameIxCols(global::SpacetimeDB.SqlTableName tableName public static partial class AssemblyDescriptor { + private static class TestDuplicateTableNameSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDuplicateTableName" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestDuplicateTableNameSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1463,10 +1511,7 @@ public readonly partial struct Queries TestDuplicateTableNameIxCols > TestDuplicateTableName() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestDuplicateTableName" - ); + var tableName = TestDuplicateTableNameSqlNameCache.Name; return new( tableName, new TestDuplicateTableNameCols(tableName), @@ -1532,6 +1577,18 @@ internal TestIndexIssuesIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class TestIndexIssuesSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestIndexIssuesSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1540,10 +1597,7 @@ public readonly partial struct Queries TestIndexIssuesIxCols > TestIndexIssues() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestIndexIssues" - ); + var tableName = TestIndexIssuesSqlNameCache.Name; return new( tableName, new TestIndexIssuesCols(tableName), @@ -1606,6 +1660,18 @@ internal TestScheduleWithoutPrimaryKeyIxCols(global::SpacetimeDB.SqlTableName ta public static partial class AssemblyDescriptor { + private static class TestScheduleWithoutPrimaryKeySqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutPrimaryKey" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithoutPrimaryKeySqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1614,10 +1680,7 @@ public readonly partial struct Queries TestScheduleWithoutPrimaryKeyIxCols > TestScheduleWithoutPrimaryKey() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithoutPrimaryKey" - ); + var tableName = TestScheduleWithoutPrimaryKeySqlNameCache.Name; return new( tableName, new TestScheduleWithoutPrimaryKeyCols(tableName), @@ -1691,6 +1754,18 @@ internal TestScheduleWithWrongPrimaryKeyTypeIxCols( public static partial class AssemblyDescriptor { + private static class TestScheduleWithWrongPrimaryKeyTypeSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongPrimaryKeyType" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithWrongPrimaryKeyTypeSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1699,10 +1774,7 @@ public readonly partial struct Queries TestScheduleWithWrongPrimaryKeyTypeIxCols > TestScheduleWithWrongPrimaryKeyType() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithWrongPrimaryKeyType" - ); + var tableName = TestScheduleWithWrongPrimaryKeyTypeSqlNameCache.Name; return new( tableName, new TestScheduleWithWrongPrimaryKeyTypeCols(tableName), @@ -1774,6 +1846,18 @@ internal TestScheduleWithoutScheduleAtIxCols(global::SpacetimeDB.SqlTableName ta public static partial class AssemblyDescriptor { + private static class TestScheduleWithoutScheduleAtSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutScheduleAt" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithoutScheduleAtSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1782,10 +1866,7 @@ public readonly partial struct Queries TestScheduleWithoutScheduleAtIxCols > TestScheduleWithoutScheduleAt() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithoutScheduleAt" - ); + var tableName = TestScheduleWithoutScheduleAtSqlNameCache.Name; return new( tableName, new TestScheduleWithoutScheduleAtCols(tableName), @@ -1859,6 +1940,18 @@ internal TestScheduleWithWrongScheduleAtTypeIxCols( public static partial class AssemblyDescriptor { + private static class TestScheduleWithWrongScheduleAtTypeSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongScheduleAtType" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithWrongScheduleAtTypeSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1867,10 +1960,7 @@ public readonly partial struct Queries TestScheduleWithWrongScheduleAtTypeIxCols > TestScheduleWithWrongScheduleAtType() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithWrongScheduleAtType" - ); + var tableName = TestScheduleWithWrongScheduleAtTypeSqlNameCache.Name; return new( tableName, new TestScheduleWithWrongScheduleAtTypeCols(tableName), @@ -1938,6 +2028,18 @@ internal TestScheduleWithMissingScheduleAtFieldIxCols( public static partial class AssemblyDescriptor { + private static class TestScheduleWithMissingScheduleAtFieldSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithMissingScheduleAtField" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithMissingScheduleAtFieldSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1946,10 +2048,7 @@ public readonly partial struct Queries TestScheduleWithMissingScheduleAtFieldIxCols > TestScheduleWithMissingScheduleAtField() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithMissingScheduleAtField" - ); + var tableName = TestScheduleWithMissingScheduleAtFieldSqlNameCache.Name; return new( tableName, new TestScheduleWithMissingScheduleAtFieldCols(tableName), @@ -2011,6 +2110,18 @@ internal TestUniqueNotEquatableIxCols(global::SpacetimeDB.SqlTableName tableName public static partial class AssemblyDescriptor { + private static class TestUniqueNotEquatableSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestUniqueNotEquatable" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestUniqueNotEquatableSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -2019,10 +2130,7 @@ public readonly partial struct Queries TestUniqueNotEquatableIxCols > TestUniqueNotEquatable() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestUniqueNotEquatable" - ); + var tableName = TestUniqueNotEquatableSqlNameCache.Name; return new( tableName, new TestUniqueNotEquatableCols(tableName), diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs index 553f927f37d..165867bf69a 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs @@ -1174,6 +1174,18 @@ internal TestDuplicateTableNameIxCols(global::SpacetimeDB.SqlTableName tableName public static partial class AssemblyDescriptor { + private static class TestDuplicateTableNameSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDuplicateTableName" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestDuplicateTableNameSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1182,10 +1194,7 @@ public readonly partial struct Queries TestDuplicateTableNameIxCols > TestDuplicateTableName() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestDuplicateTableName" - ); + var tableName = TestDuplicateTableNameSqlNameCache.Name; return new( tableName, new TestDuplicateTableNameCols(tableName), @@ -1227,14 +1236,23 @@ internal PlayerIxCols(global::SpacetimeDB.SqlTableName tableName) { } public static partial class AssemblyDescriptor { - public readonly partial struct Queries + private static class PlayerSqlNameCache { - public global::SpacetimeDB.Table Player() - { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Player" ); + + // Prevent eager initialization before the root installs namespace placements. + static PlayerSqlNameCache() { } + } + + public readonly partial struct Queries + { + public global::SpacetimeDB.Table Player() + { + var tableName = PlayerSqlNameCache.Name; return new(tableName, new PlayerCols(tableName), new PlayerIxCols(tableName)); } } @@ -1277,6 +1295,18 @@ internal TestAutoIncNotIntegerIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class TestAutoIncNotIntegerSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestAutoIncNotInteger" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestAutoIncNotIntegerSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1285,10 +1315,7 @@ public readonly partial struct Queries TestAutoIncNotIntegerIxCols > TestAutoIncNotInteger() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestAutoIncNotInteger" - ); + var tableName = TestAutoIncNotIntegerSqlNameCache.Name; return new( tableName, new TestAutoIncNotIntegerCols(tableName), @@ -1416,6 +1443,18 @@ internal TestDefaultFieldValuesIxCols(global::SpacetimeDB.SqlTableName tableName public static partial class AssemblyDescriptor { + private static class TestDefaultFieldValuesSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDefaultFieldValues" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestDefaultFieldValuesSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1424,10 +1463,7 @@ public readonly partial struct Queries TestDefaultFieldValuesIxCols > TestDefaultFieldValues() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestDefaultFieldValues" - ); + var tableName = TestDefaultFieldValuesSqlNameCache.Name; return new( tableName, new TestDefaultFieldValuesCols(tableName), @@ -1461,6 +1497,18 @@ internal TestDuplicateTableNameIxCols(global::SpacetimeDB.SqlTableName tableName public static partial class AssemblyDescriptor { + private static class TestDuplicateTableNameSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestDuplicateTableName" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestDuplicateTableNameSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1469,10 +1517,7 @@ public readonly partial struct Queries TestDuplicateTableNameIxCols > TestDuplicateTableName() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestDuplicateTableName" - ); + var tableName = TestDuplicateTableNameSqlNameCache.Name; return new( tableName, new TestDuplicateTableNameCols(tableName), @@ -1538,6 +1583,18 @@ internal TestIndexIssuesIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class TestIndexIssuesSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestIndexIssues" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestIndexIssuesSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1546,10 +1603,7 @@ public readonly partial struct Queries TestIndexIssuesIxCols > TestIndexIssues() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestIndexIssues" - ); + var tableName = TestIndexIssuesSqlNameCache.Name; return new( tableName, new TestIndexIssuesCols(tableName), @@ -1612,6 +1666,18 @@ internal TestScheduleWithoutPrimaryKeyIxCols(global::SpacetimeDB.SqlTableName ta public static partial class AssemblyDescriptor { + private static class TestScheduleWithoutPrimaryKeySqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutPrimaryKey" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithoutPrimaryKeySqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1620,10 +1686,7 @@ public readonly partial struct Queries TestScheduleWithoutPrimaryKeyIxCols > TestScheduleWithoutPrimaryKey() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithoutPrimaryKey" - ); + var tableName = TestScheduleWithoutPrimaryKeySqlNameCache.Name; return new( tableName, new TestScheduleWithoutPrimaryKeyCols(tableName), @@ -1697,6 +1760,18 @@ internal TestScheduleWithWrongPrimaryKeyTypeIxCols( public static partial class AssemblyDescriptor { + private static class TestScheduleWithWrongPrimaryKeyTypeSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongPrimaryKeyType" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithWrongPrimaryKeyTypeSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1705,10 +1780,7 @@ public readonly partial struct Queries TestScheduleWithWrongPrimaryKeyTypeIxCols > TestScheduleWithWrongPrimaryKeyType() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithWrongPrimaryKeyType" - ); + var tableName = TestScheduleWithWrongPrimaryKeyTypeSqlNameCache.Name; return new( tableName, new TestScheduleWithWrongPrimaryKeyTypeCols(tableName), @@ -1780,6 +1852,18 @@ internal TestScheduleWithoutScheduleAtIxCols(global::SpacetimeDB.SqlTableName ta public static partial class AssemblyDescriptor { + private static class TestScheduleWithoutScheduleAtSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithoutScheduleAt" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithoutScheduleAtSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1788,10 +1872,7 @@ public readonly partial struct Queries TestScheduleWithoutScheduleAtIxCols > TestScheduleWithoutScheduleAt() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithoutScheduleAt" - ); + var tableName = TestScheduleWithoutScheduleAtSqlNameCache.Name; return new( tableName, new TestScheduleWithoutScheduleAtCols(tableName), @@ -1865,6 +1946,18 @@ internal TestScheduleWithWrongScheduleAtTypeIxCols( public static partial class AssemblyDescriptor { + private static class TestScheduleWithWrongScheduleAtTypeSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithWrongScheduleAtType" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithWrongScheduleAtTypeSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1873,10 +1966,7 @@ public readonly partial struct Queries TestScheduleWithWrongScheduleAtTypeIxCols > TestScheduleWithWrongScheduleAtType() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithWrongScheduleAtType" - ); + var tableName = TestScheduleWithWrongScheduleAtTypeSqlNameCache.Name; return new( tableName, new TestScheduleWithWrongScheduleAtTypeCols(tableName), @@ -1944,6 +2034,18 @@ internal TestScheduleWithMissingScheduleAtFieldIxCols( public static partial class AssemblyDescriptor { + private static class TestScheduleWithMissingScheduleAtFieldSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestScheduleWithMissingScheduleAtField" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestScheduleWithMissingScheduleAtFieldSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1952,10 +2054,7 @@ public readonly partial struct Queries TestScheduleWithMissingScheduleAtFieldIxCols > TestScheduleWithMissingScheduleAtField() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestScheduleWithMissingScheduleAtField" - ); + var tableName = TestScheduleWithMissingScheduleAtFieldSqlNameCache.Name; return new( tableName, new TestScheduleWithMissingScheduleAtFieldCols(tableName), @@ -2017,6 +2116,18 @@ internal TestUniqueNotEquatableIxCols(global::SpacetimeDB.SqlTableName tableName public static partial class AssemblyDescriptor { + private static class TestUniqueNotEquatableSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "TestUniqueNotEquatable" + ); + + // Prevent eager initialization before the root installs namespace placements. + static TestUniqueNotEquatableSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -2025,10 +2136,7 @@ public readonly partial struct Queries TestUniqueNotEquatableIxCols > TestUniqueNotEquatable() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "TestUniqueNotEquatable" - ); + var tableName = TestUniqueNotEquatableSqlNameCache.Name; return new( tableName, new TestUniqueNotEquatableCols(tableName), diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs index fb831299a43..6a100c6cb68 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs @@ -482,6 +482,18 @@ internal DemoTableIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class DemoTableSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable" + ); + + // Prevent eager initialization before the root installs namespace placements. + static DemoTableSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -490,10 +502,7 @@ public readonly partial struct Queries DemoTableIxCols > DemoTable() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "DemoTable" - ); + var tableName = DemoTableSqlNameCache.Name; return new(tableName, new DemoTableCols(tableName), new DemoTableIxCols(tableName)); } } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs index 47f15612452..0a181cf0dde 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs @@ -487,6 +487,18 @@ internal DemoTableIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class DemoTableSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "DemoTable" + ); + + // Prevent eager initialization before the root installs namespace placements. + static DemoTableSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -495,10 +507,7 @@ public readonly partial struct Queries DemoTableIxCols > DemoTable() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "DemoTable" - ); + var tableName = DemoTableSqlNameCache.Name; return new(tableName, new DemoTableCols(tableName), new DemoTableIxCols(tableName)); } } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs index 760693ed7b2..a010611b096 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs @@ -989,6 +989,18 @@ internal BTreeMultiColumnIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class BTreeMultiColumnSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeMultiColumn" + ); + + // Prevent eager initialization before the root installs namespace placements. + static BTreeMultiColumnSqlNameCache() { } + } + public readonly partial struct Queries { internal global::SpacetimeDB.Table< @@ -997,10 +1009,7 @@ public readonly partial struct Queries BTreeMultiColumnIxCols > BTreeMultiColumn() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "BTreeMultiColumn" - ); + var tableName = BTreeMultiColumnSqlNameCache.Name; return new( tableName, new BTreeMultiColumnCols(tableName), @@ -1065,6 +1074,18 @@ internal BTreeViewsIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class BTreeViewsSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews" + ); + + // Prevent eager initialization before the root installs namespace placements. + static BTreeViewsSqlNameCache() { } + } + public readonly partial struct Queries { internal global::SpacetimeDB.Table< @@ -1073,10 +1094,7 @@ public readonly partial struct Queries BTreeViewsIxCols > BTreeViews() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "BTreeViews" - ); + var tableName = BTreeViewsSqlNameCache.Name; return new( tableName, new BTreeViewsCols(tableName), @@ -1126,6 +1144,18 @@ internal MultiTable1IxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class MultiTable1SqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1" + ); + + // Prevent eager initialization before the root installs namespace placements. + static MultiTable1SqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1134,10 +1164,7 @@ public readonly partial struct Queries MultiTable1IxCols > MultiTable1() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "MultiTable1" - ); + var tableName = MultiTable1SqlNameCache.Name; return new( tableName, new MultiTable1Cols(tableName), @@ -1180,6 +1207,18 @@ internal MultiTable2IxCols(global::SpacetimeDB.SqlTableName tableName) { } public static partial class AssemblyDescriptor { + private static class MultiTable2SqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable2" + ); + + // Prevent eager initialization before the root installs namespace placements. + static MultiTable2SqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1188,10 +1227,7 @@ public readonly partial struct Queries MultiTable2IxCols > MultiTable2() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "MultiTable2" - ); + var tableName = MultiTable2SqlNameCache.Name; return new( tableName, new MultiTable2Cols(tableName), @@ -1225,6 +1261,18 @@ internal PrivateTableIxCols(global::SpacetimeDB.SqlTableName tableName) { } public static partial class AssemblyDescriptor { + private static class PrivateTableSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PrivateTable" + ); + + // Prevent eager initialization before the root installs namespace placements. + static PrivateTableSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1233,10 +1281,7 @@ public readonly partial struct Queries PrivateTableIxCols > PrivateTable() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "PrivateTable" - ); + var tableName = PrivateTableSqlNameCache.Name; return new( tableName, new PrivateTableCols(tableName), @@ -1427,6 +1472,18 @@ internal PublicTableIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class PublicTableSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PublicTable" + ); + + // Prevent eager initialization before the root installs namespace placements. + static PublicTableSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1435,10 +1492,7 @@ public readonly partial struct Queries PublicTableIxCols > PublicTable() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "PublicTable" - ); + var tableName = PublicTableSqlNameCache.Name; return new( tableName, new PublicTableCols(tableName), @@ -1495,6 +1549,18 @@ internal RegressionMultipleUniqueIndexesHadSameNameIxCols( public static partial class AssemblyDescriptor { + private static class RegressionMultipleUniqueIndexesHadSameNameSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName" + ); + + // Prevent eager initialization before the root installs namespace placements. + static RegressionMultipleUniqueIndexesHadSameNameSqlNameCache() { } + } + public readonly partial struct Queries { internal global::SpacetimeDB.Table< @@ -1503,10 +1569,7 @@ public readonly partial struct Queries RegressionMultipleUniqueIndexesHadSameNameIxCols > RegressionMultipleUniqueIndexesHadSameName() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "RegressionMultipleUniqueIndexesHadSameName" - ); + var tableName = RegressionMultipleUniqueIndexesHadSameNameSqlNameCache.Name; return new( tableName, new RegressionMultipleUniqueIndexesHadSameNameCols(tableName), @@ -1573,6 +1636,18 @@ internal SendMessageTimerIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class SendMessageTimerSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "SendMessageTimer" + ); + + // Prevent eager initialization before the root installs namespace placements. + static SendMessageTimerSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1581,10 +1656,7 @@ public readonly partial struct Queries SendMessageTimerIxCols > SendMessageTimer() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "SendMessageTimer" - ); + var tableName = SendMessageTimerSqlNameCache.Name; return new( tableName, new SendMessageTimerCols(tableName), diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs index 141faa88f64..ed901de7a04 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs @@ -1005,6 +1005,18 @@ internal BTreeMultiColumnIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class BTreeMultiColumnSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeMultiColumn" + ); + + // Prevent eager initialization before the root installs namespace placements. + static BTreeMultiColumnSqlNameCache() { } + } + public readonly partial struct Queries { internal global::SpacetimeDB.Table< @@ -1013,10 +1025,7 @@ public readonly partial struct Queries BTreeMultiColumnIxCols > BTreeMultiColumn() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "BTreeMultiColumn" - ); + var tableName = BTreeMultiColumnSqlNameCache.Name; return new( tableName, new BTreeMultiColumnCols(tableName), @@ -1081,6 +1090,18 @@ internal BTreeViewsIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class BTreeViewsSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "BTreeViews" + ); + + // Prevent eager initialization before the root installs namespace placements. + static BTreeViewsSqlNameCache() { } + } + public readonly partial struct Queries { internal global::SpacetimeDB.Table< @@ -1089,10 +1110,7 @@ public readonly partial struct Queries BTreeViewsIxCols > BTreeViews() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "BTreeViews" - ); + var tableName = BTreeViewsSqlNameCache.Name; return new( tableName, new BTreeViewsCols(tableName), @@ -1142,6 +1160,18 @@ internal MultiTable1IxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class MultiTable1SqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable1" + ); + + // Prevent eager initialization before the root installs namespace placements. + static MultiTable1SqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1150,10 +1180,7 @@ public readonly partial struct Queries MultiTable1IxCols > MultiTable1() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "MultiTable1" - ); + var tableName = MultiTable1SqlNameCache.Name; return new( tableName, new MultiTable1Cols(tableName), @@ -1196,6 +1223,18 @@ internal MultiTable2IxCols(global::SpacetimeDB.SqlTableName tableName) { } public static partial class AssemblyDescriptor { + private static class MultiTable2SqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "MultiTable2" + ); + + // Prevent eager initialization before the root installs namespace placements. + static MultiTable2SqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1204,10 +1243,7 @@ public readonly partial struct Queries MultiTable2IxCols > MultiTable2() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "MultiTable2" - ); + var tableName = MultiTable2SqlNameCache.Name; return new( tableName, new MultiTable2Cols(tableName), @@ -1241,6 +1277,18 @@ internal PrivateTableIxCols(global::SpacetimeDB.SqlTableName tableName) { } public static partial class AssemblyDescriptor { + private static class PrivateTableSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PrivateTable" + ); + + // Prevent eager initialization before the root installs namespace placements. + static PrivateTableSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1249,10 +1297,7 @@ public readonly partial struct Queries PrivateTableIxCols > PrivateTable() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "PrivateTable" - ); + var tableName = PrivateTableSqlNameCache.Name; return new( tableName, new PrivateTableCols(tableName), @@ -1443,6 +1488,18 @@ internal PublicTableIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class PublicTableSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "PublicTable" + ); + + // Prevent eager initialization before the root installs namespace placements. + static PublicTableSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1451,10 +1508,7 @@ public readonly partial struct Queries PublicTableIxCols > PublicTable() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "PublicTable" - ); + var tableName = PublicTableSqlNameCache.Name; return new( tableName, new PublicTableCols(tableName), @@ -1511,6 +1565,18 @@ internal RegressionMultipleUniqueIndexesHadSameNameIxCols( public static partial class AssemblyDescriptor { + private static class RegressionMultipleUniqueIndexesHadSameNameSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "RegressionMultipleUniqueIndexesHadSameName" + ); + + // Prevent eager initialization before the root installs namespace placements. + static RegressionMultipleUniqueIndexesHadSameNameSqlNameCache() { } + } + public readonly partial struct Queries { internal global::SpacetimeDB.Table< @@ -1519,10 +1585,7 @@ public readonly partial struct Queries RegressionMultipleUniqueIndexesHadSameNameIxCols > RegressionMultipleUniqueIndexesHadSameName() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "RegressionMultipleUniqueIndexesHadSameName" - ); + var tableName = RegressionMultipleUniqueIndexesHadSameNameSqlNameCache.Name; return new( tableName, new RegressionMultipleUniqueIndexesHadSameNameCols(tableName), @@ -1589,6 +1652,18 @@ internal SendMessageTimerIxCols(global::SpacetimeDB.SqlTableName tableName) public static partial class AssemblyDescriptor { + private static class SendMessageTimerSqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "SendMessageTimer" + ); + + // Prevent eager initialization before the root installs namespace placements. + static SendMessageTimerSqlNameCache() { } + } + public readonly partial struct Queries { public global::SpacetimeDB.Table< @@ -1597,10 +1672,7 @@ public readonly partial struct Queries SendMessageTimerIxCols > SendMessageTimer() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "SendMessageTimer" - ); + var tableName = SendMessageTimerSqlNameCache.Name; return new( tableName, new SendMessageTimerCols(tableName), diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 4f041d31e88..57f53a8ce08 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -1023,11 +1023,19 @@ string IxColInit(ColumnDeclaration col) ? $$""" public static partial class AssemblyDescriptor { + private static class {{accessorIdentifier}}SqlNameCache + { + internal static readonly global::SpacetimeDB.SqlTableName Name = + global::SpacetimeDB.Internal.Module.ResolveSqlName({{SymbolDisplay.FormatLiteral(assemblyIdentity, true)}}, {{SymbolDisplay.FormatLiteral(tableName, true)}}); + // Prevent eager initialization before the root installs namespace placements. + static {{accessorIdentifier}}SqlNameCache() { } + } + public readonly partial struct Queries { {{vis}} {{queryType}} {{accessorIdentifier}}() { - var tableName = global::SpacetimeDB.Internal.Module.ResolveSqlName({{SymbolDisplay.FormatLiteral(assemblyIdentity, true)}}, {{SymbolDisplay.FormatLiteral(tableName, true)}}); + var tableName = {{accessorIdentifier}}SqlNameCache.Name; return new(tableName, new {{colsTypeName}}(tableName), new {{ixColsTypeName}}(tableName)); } } From 6eb91a53ed653f55a302b577234392d522bd507d Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Mon, 21 Sep 2026 14:58:10 -0500 Subject: [PATCH 24/49] Resolve namespaces only once in clients --- crates/codegen/src/csharp.rs | 8 +++-- .../tests/csharp-namespaces/Program.cs | 29 +++++++++++++++++++ .../module_bindings/MyAuth/Namespace.g.cs | 14 ++++----- .../MyAuth/Tables/AnonymousUsers.g.cs | 3 +- .../module_bindings/MyAuth/Tables/Notice.g.cs | 3 +- .../MyAuth/Tables/ProtectedRow.g.cs | 3 +- .../MyAuth/Tables/QueryUsers.g.cs | 3 +- .../MyAuth/Tables/ScheduleResult.g.cs | 3 +- .../module_bindings/MyAuth/Tables/User.g.cs | 3 +- .../module_bindings/MyAuth/Tables/Users.g.cs | 3 +- .../module_bindings/SpacetimeDBClient.g.cs | 2 +- .../module_bindings/class/Namespace.g.cs | 4 +-- .../class/Tables/ScheduleResult.g.cs | 3 +- .../module_bindings/class/Tables/User.g.cs | 3 +- 14 files changed, 63 insertions(+), 21 deletions(-) diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs index 58c4f186383..30d475abf28 100644 --- a/crates/codegen/src/csharp.rs +++ b/crates/codegen/src/csharp.rs @@ -695,7 +695,7 @@ impl CsharpScope<'_> { let table_name_lit = if self.path.is_empty() { format!("{:?}", name.deref()) } else { - self.sql_name(name) + format!("RemoteTables.{method_name}Handle.SqlName") }; writeln!(output, "public global::SpacetimeDB.Table<{row_type}, {method_name}Cols, {method_name}IxCols> {method_name}() => new({table_name_lit}, new {method_name}Cols({table_name_lit}), new {method_name}IxCols({table_name_lit}));"); } @@ -778,9 +778,13 @@ impl Lang for CsharpScope<'_> { if !self.path.is_empty() { writeln!( output, - "protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => {};", + "internal static readonly global::SpacetimeDB.SqlTableName SqlName = {};", self.sql_name(&table.name) ); + writeln!( + output, + "protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName;" + ); } writeln!(output); diff --git a/crates/codegen/tests/csharp-namespaces/Program.cs b/crates/codegen/tests/csharp-namespaces/Program.cs index f04cef38917..cbc31761ca5 100644 --- a/crates/codegen/tests/csharp-namespaces/Program.cs +++ b/crates/codegen/tests/csharp-namespaces/Program.cs @@ -61,6 +61,15 @@ private static void Main() } } + private static void CheckCachedSqlName(object value, SqlTableName expected) + { + var field = value.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic) + .Single(f => f.FieldType == typeof(SqlTableName)); + var actual = (SqlTableName)field.GetValue(value)!; + Equal(expected.LocalName, actual.LocalName); + Equal(true, ReferenceEquals(expected.NamespaceSegments, actual.NamespaceSegments)); + } + private static void Check(DbConnection conn) { Equal("user", conn.Db.User.RemoteTableName); @@ -84,6 +93,26 @@ private static void Check(DbConnection conn) Equal(false, all.Any(sql => sql.Contains("secret"))); var sqlName = typeof(Auth.RemoteTables.UserHandle).GetProperty("RemoteSqlTableName", BindingFlags.Instance | BindingFlags.NonPublic)!; Equal("\"MyAuth\".\"user\"", sqlName.GetValue(conn.Db.MyAuth.User)!.ToString()); + var cachedName = Auth.RemoteTables.UserHandle.SqlName; + for (var i = 0; i < 2; i++) + Equal(true, ReferenceEquals(cachedName.NamespaceSegments, + ((SqlTableName)sqlName.GetValue(conn.Db.MyAuth.User)!).NamespaceSegments)); + var firstQuery = query.From.MyAuth.User(); + var secondQuery = query.From.MyAuth.User(); + Equal(false, ReferenceEquals(firstQuery, secondQuery)); + foreach (var tableQuery in new[] { firstQuery, secondQuery }) + { + CheckCachedSqlName(tableQuery, cachedName); + foreach (var property in new[] { "Cols", "IxCols" }) + { + var columns = tableQuery.GetType().GetProperty(property, + BindingFlags.Instance | BindingFlags.NonPublic)!.GetValue(tableQuery)!; + foreach (var column in columns.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public)) + CheckCachedSqlName(column.GetValue(columns)!, cachedName); + } + } + Equal(false, ReferenceEquals(cachedName.NamespaceSegments, + Audit.RemoteTables.UserHandle.SqlName.NamespaceSegments)); var root = new User(1, true); var auth = new Auth.User(1, 7); diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs index a1bbea5e3df..96e74b016ae 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Namespace.g.cs @@ -34,13 +34,13 @@ internal RemoteTables(global::SpacetimeDB.Types.DbConnection conn, Action AnonymousUsers() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users"), new AnonymousUsersCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users")), new AnonymousUsersIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users"))); - public global::SpacetimeDB.Table Notice() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice"), new NoticeCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice")), new NoticeIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice"))); - public global::SpacetimeDB.Table ProtectedRow() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "protected_row"), new ProtectedRowCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "protected_row")), new ProtectedRowIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "protected_row"))); - public global::SpacetimeDB.Table QueryUsers() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users"), new QueryUsersCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users")), new QueryUsersIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users"))); - public global::SpacetimeDB.Table ScheduleResult() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "schedule_result"), new ScheduleResultCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "schedule_result")), new ScheduleResultIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "schedule_result"))); - public global::SpacetimeDB.Table User() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users"), new UserCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users")), new UserIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users"))); - public global::SpacetimeDB.Table Users() => new(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "users"), new UsersCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "users")), new UsersIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "users"))); + public global::SpacetimeDB.Table AnonymousUsers() => new(RemoteTables.AnonymousUsersHandle.SqlName, new AnonymousUsersCols(RemoteTables.AnonymousUsersHandle.SqlName), new AnonymousUsersIxCols(RemoteTables.AnonymousUsersHandle.SqlName)); + public global::SpacetimeDB.Table Notice() => new(RemoteTables.NoticeHandle.SqlName, new NoticeCols(RemoteTables.NoticeHandle.SqlName), new NoticeIxCols(RemoteTables.NoticeHandle.SqlName)); + public global::SpacetimeDB.Table ProtectedRow() => new(RemoteTables.ProtectedRowHandle.SqlName, new ProtectedRowCols(RemoteTables.ProtectedRowHandle.SqlName), new ProtectedRowIxCols(RemoteTables.ProtectedRowHandle.SqlName)); + public global::SpacetimeDB.Table QueryUsers() => new(RemoteTables.QueryUsersHandle.SqlName, new QueryUsersCols(RemoteTables.QueryUsersHandle.SqlName), new QueryUsersIxCols(RemoteTables.QueryUsersHandle.SqlName)); + public global::SpacetimeDB.Table ScheduleResult() => new(RemoteTables.ScheduleResultHandle.SqlName, new ScheduleResultCols(RemoteTables.ScheduleResultHandle.SqlName), new ScheduleResultIxCols(RemoteTables.ScheduleResultHandle.SqlName)); + public global::SpacetimeDB.Table User() => new(RemoteTables.UserHandle.SqlName, new UserCols(RemoteTables.UserHandle.SqlName), new UserIxCols(RemoteTables.UserHandle.SqlName)); + public global::SpacetimeDB.Table Users() => new(RemoteTables.UsersHandle.SqlName, new UsersCols(RemoteTables.UsersHandle.SqlName), new UsersIxCols(RemoteTables.UsersHandle.SqlName)); } public abstract partial class Reducer diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs index 65b28e43872..755f3a55dc7 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs @@ -16,7 +16,8 @@ public sealed partial class RemoteTables public sealed class AnonymousUsersHandle : RemoteTableHandle { public override string RemoteTableName => "MyAuth.anonymous_users"; - protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users"); + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; internal AnonymousUsersHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) { diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs index 89215cafc7f..affc88589a2 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs @@ -16,7 +16,8 @@ public sealed partial class RemoteTables public sealed class NoticeHandle : RemoteEventTableHandle { public override string RemoteTableName => "MyAuth.notice"; - protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice"); + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; internal NoticeHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) { diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs index a3a8179df79..a9c089caf9e 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs @@ -16,7 +16,8 @@ public sealed partial class RemoteTables public sealed class ProtectedRowHandle : RemoteTableHandle { public override string RemoteTableName => "MyAuth.protected_row"; - protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "protected_row"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "protected_row"); + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class IdUniqueIndex : UniqueIndexBase { diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs index f50754f4634..73eadac07fc 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs @@ -16,7 +16,8 @@ public sealed partial class RemoteTables public sealed class QueryUsersHandle : RemoteTableHandle { public override string RemoteTableName => "MyAuth.query_users"; - protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users"); + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class IdUniqueIndex : UniqueIndexBase { diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs index 8bc0c3379d9..dfb1a9ad6b2 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs @@ -16,7 +16,8 @@ public sealed partial class RemoteTables public sealed class ScheduleResultHandle : RemoteTableHandle { public override string RemoteTableName => "MyAuth.schedule_result"; - protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "schedule_result"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "schedule_result"); + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class JobIdUniqueIndex : UniqueIndexBase { diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs index 472635e390f..88fea38b560 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs @@ -16,7 +16,8 @@ public sealed partial class RemoteTables public sealed class UserHandle : RemoteTableHandle { public override string RemoteTableName => "MyAuth.auth_users"; - protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users"); + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class IdUniqueIndex : UniqueIndexBase { diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs index ff067caa321..ee3adfce836 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs @@ -16,7 +16,8 @@ public sealed partial class RemoteTables public sealed class UsersHandle : RemoteTableHandle { public override string RemoteTableName => "MyAuth.users"; - protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "users"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "users"); + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; internal UsersHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) { diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs index 26e44ec34e0..ad397d36f08 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.10.1 (commit 7109fe86a665ba5404389ce72ffc63131bf576cc). +// This was generated using spacetimedb cli version 2.10.1 (commit 9604ff61789b002b5fc92b43b12887aa54a369a4). #nullable enable diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Namespace.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Namespace.g.cs index 5a16f7f33ed..367b0c7cf3c 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Namespace.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Namespace.g.cs @@ -29,8 +29,8 @@ internal RemoteTables(global::SpacetimeDB.Types.DbConnection conn, Action ScheduleResult() => new(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "schedule_result"), new ScheduleResultCols(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "schedule_result")), new ScheduleResultIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "schedule_result"))); - public global::SpacetimeDB.Table User() => new(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "user"), new UserCols(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "user")), new UserIxCols(new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "user"))); + public global::SpacetimeDB.Table ScheduleResult() => new(RemoteTables.ScheduleResultHandle.SqlName, new ScheduleResultCols(RemoteTables.ScheduleResultHandle.SqlName), new ScheduleResultIxCols(RemoteTables.ScheduleResultHandle.SqlName)); + public global::SpacetimeDB.Table User() => new(RemoteTables.UserHandle.SqlName, new UserCols(RemoteTables.UserHandle.SqlName), new UserIxCols(RemoteTables.UserHandle.SqlName)); } public abstract partial class Reducer diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/ScheduleResult.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/ScheduleResult.g.cs index 44a53746ffa..823bc45e4b2 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/ScheduleResult.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/ScheduleResult.g.cs @@ -16,7 +16,8 @@ public sealed partial class RemoteTables public sealed class ScheduleResultHandle : RemoteTableHandle { public override string RemoteTableName => "class.schedule_result"; - protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "schedule_result"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "schedule_result"); + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class JobIdUniqueIndex : UniqueIndexBase { diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/User.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/User.g.cs index c769b9fadbe..6d68770f97f 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/User.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/User.g.cs @@ -16,7 +16,8 @@ public sealed partial class RemoteTables public sealed class UserHandle : RemoteTableHandle { public override string RemoteTableName => "class.user"; - protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "user"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "user"); + protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class IdUniqueIndex : UniqueIndexBase { From 8d8fb3eaf8eff83d077c633e030bd439ce9827c0 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Mon, 21 Sep 2026 15:08:57 -0500 Subject: [PATCH 25/49] Resolve namespaces only once in reducers --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 17 ++++++++++- ...space.TestDuplicateReducerName.verified.cs | 16 ++++++++--- ...rs.OnReducerWithReservedPrefix.verified.cs | 16 ++++++++--- ...cers.TestDuplicateReducerKind1.verified.cs | 16 ++++++++--- ...cers.TestDuplicateReducerKind2.verified.cs | 16 ++++++++--- ...ucers.TestDuplicateReducerName.verified.cs | 16 ++++++++--- ...Reducers.TestReducerReturnType.verified.cs | 16 ++++++++--- ...cers.TestReducerWithoutContext.verified.cs | 16 ++++++++--- ...rs.__ReducerWithReservedPrefix.verified.cs | 16 ++++++++--- ...leIssues.DummyScheduledReducer.verified.cs | 16 ++++++++--- ...e.net10#Reducers.DemoProcedure.verified.cs | 16 ++++++++--- ...ule.net10#Reducers.DemoReducer.verified.cs | 16 ++++++++--- ...#MultiTableRow.InsertMultiData.verified.cs | 16 ++++++++--- ...dule.net10#Reducers.InsertData.verified.cs | 16 ++++++++--- ...t10#Reducers.ScheduleImmediate.verified.cs | 16 ++++++++--- ...espaces.AndClasses.InsertData2.verified.cs | 16 ++++++++--- .../Module.net10#Timers.Init.verified.cs | 16 ++++++++--- ...10#Timers.SendScheduledMessage.verified.cs | 16 ++++++++--- crates/bindings-csharp/Codegen/Module.cs | 28 +++++++++++++++++-- 19 files changed, 246 insertions(+), 71 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 3e17309300b..edde1445b8f 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -326,6 +326,10 @@ public static partial class Jobs public static void ReducerTick(SpacetimeDB.ReducerContext ctx, uint payload) { } [SpacetimeDB.Procedure(Name = "procedure_job")] public static void ProcedureTick(SpacetimeDB.ProcedureContext ctx, uint payload) { } + [SpacetimeDB.Reducer] + public static void DefaultReducer(SpacetimeDB.ReducerContext ctx) { } + [SpacetimeDB.Procedure] + public static void DefaultProcedure(SpacetimeDB.ProcedureContext ctx) { } } """; var input = CSharpCompilation.Create( @@ -346,6 +350,8 @@ public static void ProcedureTick(SpacetimeDB.ProcedureContext ctx, uint payload) { ("ReducerTick", "reducer_job"), ("ProcedureTick", "procedure_job"), + ("DefaultReducer", "DefaultReducer"), + ("DefaultProcedure", "DefaultProcedure"), }) { var helper = Assert.Single(output.SyntaxTrees @@ -358,7 +364,16 @@ public static void ProcedureTick(SpacetimeDB.ProcedureContext ctx, uint payload) var name = call.ArgumentList.Arguments[0].Expression; if (framework == "net10.0") { - var resolve = Assert.IsType(name); + var field = Assert.IsAssignableFrom(output.GetSemanticModel(name.SyntaxTree) + .GetSymbolInfo(name).Symbol); + Assert.True(field.IsStatic); + Assert.True(field.IsReadOnly); + Assert.Contains(field.ContainingType.StaticConstructors, ctor => !ctor.IsImplicitlyDeclared); + Assert.DoesNotContain(helper.DescendantNodes().OfType(), + invocation => invocation.Expression.ToString().EndsWith(".ResolveName")); + var declaration = Assert.IsType( + Assert.Single(field.DeclaringSyntaxReferences).GetSyntax()); + var resolve = Assert.IsType(declaration.Initializer!.Value); Assert.Equal("global::SpacetimeDB.Internal.Module.ResolveName", resolve.Expression.ToString()); Assert.StartsWith("ScheduledLibrary,", (string)output.GetSemanticModel(resolve.SyntaxTree) .GetConstantValue(resolve.ArgumentList.Arguments[0].Expression).Value!); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.InAnotherNamespace.TestDuplicateReducerName.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.InAnotherNamespace.TestDuplicateReducerName.verified.cs index 7614878cfbb..96ae102944a 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.InAnotherNamespace.TestDuplicateReducerName.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.InAnotherNamespace.TestDuplicateReducerName.verified.cs @@ -6,6 +6,17 @@ partial class Reducers { partial class InAnotherNamespace { + private static class __ScheduleTestDuplicateReducerNameName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestDuplicateReducerName) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleTestDuplicateReducerNameName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateTestDuplicateReducerName() { @@ -13,10 +24,7 @@ public static void VolatileNonatomicScheduleImmediateTestDuplicateReducerName() using var writer = new BinaryWriter(stream); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(TestDuplicateReducerName) - ), + __ScheduleTestDuplicateReducerNameName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.OnReducerWithReservedPrefix.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.OnReducerWithReservedPrefix.verified.cs index 913aa1b37bc..0c87fdbea54 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.OnReducerWithReservedPrefix.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.OnReducerWithReservedPrefix.verified.cs @@ -4,6 +4,17 @@ partial class Reducers { + private static class __ScheduleOnReducerWithReservedPrefixName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(OnReducerWithReservedPrefix) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleOnReducerWithReservedPrefixName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateOnReducerWithReservedPrefix() { @@ -11,10 +22,7 @@ public static void VolatileNonatomicScheduleImmediateOnReducerWithReservedPrefix using var writer = new BinaryWriter(stream); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(OnReducerWithReservedPrefix) - ), + __ScheduleOnReducerWithReservedPrefixName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind1.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind1.verified.cs index 4dc5091936a..0fcda17d08b 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind1.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind1.verified.cs @@ -4,6 +4,17 @@ partial class Reducers { + private static class __ScheduleTestDuplicateReducerKind1Name + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestDuplicateReducerKind1) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleTestDuplicateReducerKind1Name() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateTestDuplicateReducerKind1() { @@ -11,10 +22,7 @@ public static void VolatileNonatomicScheduleImmediateTestDuplicateReducerKind1() using var writer = new BinaryWriter(stream); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(TestDuplicateReducerKind1) - ), + __ScheduleTestDuplicateReducerKind1Name.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind2.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind2.verified.cs index d2fec96e7fc..1130b799c6d 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind2.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind2.verified.cs @@ -4,6 +4,17 @@ partial class Reducers { + private static class __ScheduleTestDuplicateReducerKind2Name + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestDuplicateReducerKind2) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleTestDuplicateReducerKind2Name() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateTestDuplicateReducerKind2() { @@ -11,10 +22,7 @@ public static void VolatileNonatomicScheduleImmediateTestDuplicateReducerKind2() using var writer = new BinaryWriter(stream); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(TestDuplicateReducerKind2) - ), + __ScheduleTestDuplicateReducerKind2Name.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerName.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerName.verified.cs index cfa14ab306a..dd21f02b945 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerName.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerName.verified.cs @@ -4,6 +4,17 @@ partial class Reducers { + private static class __ScheduleTestDuplicateReducerNameName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestDuplicateReducerName) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleTestDuplicateReducerNameName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateTestDuplicateReducerName() { @@ -11,10 +22,7 @@ public static void VolatileNonatomicScheduleImmediateTestDuplicateReducerName() using var writer = new BinaryWriter(stream); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(TestDuplicateReducerName) - ), + __ScheduleTestDuplicateReducerNameName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerReturnType.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerReturnType.verified.cs index 6b5a7281456..70eebe7d781 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerReturnType.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerReturnType.verified.cs @@ -4,6 +4,17 @@ partial class Reducers { + private static class __ScheduleTestReducerReturnTypeName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestReducerReturnType) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleTestReducerReturnTypeName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateTestReducerReturnType() { @@ -11,10 +22,7 @@ public static void VolatileNonatomicScheduleImmediateTestReducerReturnType() using var writer = new BinaryWriter(stream); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(TestReducerReturnType) - ), + __ScheduleTestReducerReturnTypeName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerWithoutContext.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerWithoutContext.verified.cs index d93e91533f0..f2a42b640ef 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerWithoutContext.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerWithoutContext.verified.cs @@ -4,6 +4,17 @@ partial class Reducers { + private static class __ScheduleTestReducerWithoutContextName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestReducerWithoutContext) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleTestReducerWithoutContextName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateTestReducerWithoutContext() { @@ -11,10 +22,7 @@ public static void VolatileNonatomicScheduleImmediateTestReducerWithoutContext() using var writer = new BinaryWriter(stream); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(TestReducerWithoutContext) - ), + __ScheduleTestReducerWithoutContextName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.__ReducerWithReservedPrefix.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.__ReducerWithReservedPrefix.verified.cs index 24c4515c3e1..0978d0cf077 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.__ReducerWithReservedPrefix.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.__ReducerWithReservedPrefix.verified.cs @@ -4,6 +4,17 @@ partial class Reducers { + private static class __Schedule__ReducerWithReservedPrefixName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(__ReducerWithReservedPrefix) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __Schedule__ReducerWithReservedPrefixName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediate__ReducerWithReservedPrefix() { @@ -11,10 +22,7 @@ public static void VolatileNonatomicScheduleImmediate__ReducerWithReservedPrefix using var writer = new BinaryWriter(stream); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(__ReducerWithReservedPrefix) - ), + __Schedule__ReducerWithReservedPrefixName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.DummyScheduledReducer.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.DummyScheduledReducer.verified.cs index 7bd10b3a732..c62d296ba4c 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.DummyScheduledReducer.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.DummyScheduledReducer.verified.cs @@ -4,6 +4,17 @@ partial struct TestScheduleIssues { + private static class __ScheduleDummyScheduledReducerName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(DummyScheduledReducer) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleDummyScheduledReducerName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateDummyScheduledReducer( TestScheduleIssues table @@ -13,10 +24,7 @@ TestScheduleIssues table using var writer = new BinaryWriter(stream); new TestScheduleIssues.BSATN().Write(writer, table); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(DummyScheduledReducer) - ), + __ScheduleDummyScheduledReducerName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoProcedure.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoProcedure.verified.cs index 8be427ec77d..19fe4ca6d71 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoProcedure.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoProcedure.verified.cs @@ -4,6 +4,17 @@ partial class Reducers { + private static class __ScheduleDemoProcedureName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "canonical_procedure" + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleDemoProcedureName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateDemoProcedure() { @@ -11,10 +22,7 @@ public static void VolatileNonatomicScheduleImmediateDemoProcedure() using var writer = new BinaryWriter(stream); SpacetimeDB.Internal.ProcedureExtensions.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "canonical_procedure" - ), + __ScheduleDemoProcedureName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoReducer.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoReducer.verified.cs index a907e229d4a..0a32e3cb75e 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoReducer.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoReducer.verified.cs @@ -4,6 +4,17 @@ partial class Reducers { + private static class __ScheduleDemoReducerName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "canonical_reducer" + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleDemoReducerName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateDemoReducer(int value) { @@ -11,10 +22,7 @@ public static void VolatileNonatomicScheduleImmediateDemoReducer(int value) using var writer = new BinaryWriter(stream); new SpacetimeDB.BSATN.I32().Write(writer, value); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "canonical_reducer" - ), + __ScheduleDemoReducerName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.InsertMultiData.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.InsertMultiData.verified.cs index d063fd6f7b2..f2f4796ce76 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.InsertMultiData.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.InsertMultiData.verified.cs @@ -4,6 +4,17 @@ partial struct MultiTableRow { + private static class __ScheduleInsertMultiDataName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(InsertMultiData) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleInsertMultiDataName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateInsertMultiData(MultiTableRow data) { @@ -11,10 +22,7 @@ public static void VolatileNonatomicScheduleImmediateInsertMultiData(MultiTableR using var writer = new BinaryWriter(stream); new MultiTableRow.BSATN().Write(writer, data); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(InsertMultiData) - ), + __ScheduleInsertMultiDataName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.InsertData.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.InsertData.verified.cs index 52cdd4b59ac..8feb994bc57 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.InsertData.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.InsertData.verified.cs @@ -4,6 +4,17 @@ partial class Reducers { + private static class __ScheduleInsertDataName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(InsertData) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleInsertDataName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateInsertData(PublicTable data) { @@ -11,10 +22,7 @@ public static void VolatileNonatomicScheduleImmediateInsertData(PublicTable data using var writer = new BinaryWriter(stream); new PublicTable.BSATN().Write(writer, data); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(InsertData) - ), + __ScheduleInsertDataName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.ScheduleImmediate.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.ScheduleImmediate.verified.cs index 5f3498a3fbe..bc08c9e2acb 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.ScheduleImmediate.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.ScheduleImmediate.verified.cs @@ -4,6 +4,17 @@ partial class Reducers { + private static class __ScheduleScheduleImmediateName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(ScheduleImmediate) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleScheduleImmediateName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateScheduleImmediate(PublicTable data) { @@ -11,10 +22,7 @@ public static void VolatileNonatomicScheduleImmediateScheduleImmediate(PublicTab using var writer = new BinaryWriter(stream); new PublicTable.BSATN().Write(writer, data); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(ScheduleImmediate) - ), + __ScheduleScheduleImmediateName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs index 5fc1e766688..4c7cf63ba0a 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs @@ -6,6 +6,17 @@ namespace Test.NestingNamespaces { partial class AndClasses { + private static class __ScheduleInsertData2Name + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(InsertData2) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleInsertData2Name() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateInsertData2(PublicTable data) { @@ -13,10 +24,7 @@ public static void VolatileNonatomicScheduleImmediateInsertData2(PublicTable dat using var writer = new BinaryWriter(stream); new PublicTable.BSATN().Write(writer, data); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(InsertData2) - ), + __ScheduleInsertData2Name.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.Init.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.Init.verified.cs index 61a3f46c69d..4700a0f58e7 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.Init.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.Init.verified.cs @@ -4,6 +4,17 @@ partial class Timers { + private static class __ScheduleInitName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(Init) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleInitName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateInit() { @@ -11,10 +22,7 @@ public static void VolatileNonatomicScheduleImmediateInit() using var writer = new BinaryWriter(stream); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(Init) - ), + __ScheduleInitName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendScheduledMessage.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendScheduledMessage.verified.cs index 04376ee92b9..679d0ff1e91 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendScheduledMessage.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendScheduledMessage.verified.cs @@ -4,6 +4,17 @@ partial class Timers { + private static class __ScheduleSendScheduledMessageName + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(SendScheduledMessage) + ); + + // Prevent eager initialization before the root installs namespace placements. + static __ScheduleSendScheduledMessageName() { } + } + [System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] public static void VolatileNonatomicScheduleImmediateSendScheduledMessage( Timers.SendMessageTimer arg @@ -13,10 +24,7 @@ Timers.SendMessageTimer arg using var writer = new BinaryWriter(stream); new Timers.SendMessageTimer.BSATN().Write(writer, arg); SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate( - global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(SendScheduledMessage) - ), + __ScheduleSendScheduledMessageName.Name, stream ); } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 57f53a8ce08..72de722e85b 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -1667,7 +1667,19 @@ public Scope.Extensions GenerateSchedule() ? $"nameof({Identifier})" : SymbolDisplay.FormatLiteral(CanonicalName!, true); if (declaringAssembly is not null) - functionName = $"global::SpacetimeDB.Internal.Module.ResolveName({SymbolDisplay.FormatLiteral(declaringAssembly, true)}, {functionName})"; + { + var cacheName = $"__Schedule{Name}Name"; + extensions.Contents.Append($$""" + private static class {{cacheName}} + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName({{SymbolDisplay.FormatLiteral(declaringAssembly, true)}}, {{functionName}}); + // Prevent eager initialization before the root installs namespace placements. + static {{cacheName}}() { } + } + + """); + functionName = cacheName + ".Name"; + } // Mark the API as unstable. We use name `STDB_UNSTABLE` because: // 1. It's a close equivalent of the `unstable` Cargo feature in Rust. @@ -1896,7 +1908,19 @@ public Scope.Extensions GenerateSchedule() ? $"nameof({Identifier})" : SymbolDisplay.FormatLiteral(CanonicalName!, true); if (declaringAssembly is not null) - functionName = $"global::SpacetimeDB.Internal.Module.ResolveName({SymbolDisplay.FormatLiteral(declaringAssembly, true)}, {functionName})"; + { + var cacheName = $"__Schedule{Name}Name"; + extensions.Contents.Append($$""" + private static class {{cacheName}} + { + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName({{SymbolDisplay.FormatLiteral(declaringAssembly, true)}}, {{functionName}}); + // Prevent eager initialization before the root installs namespace placements. + static {{cacheName}}() { } + } + + """); + functionName = cacheName + ".Name"; + } // Mark the API as unstable. We use name `STDB_UNSTABLE` because: // 1. It's a close equivalent of the `unstable` Cargo feature in Rust. From 80e0c2034186dc9b2c35215944a4d88b92c03bb1 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Tue, 22 Sep 2026 13:12:18 -0500 Subject: [PATCH 26/49] Codex suggested CI change --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2cd75fb205..9017ac7bf41 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1430,9 +1430,9 @@ jobs: working-directory: sdks/csharp run: dotnet restore --configfile NuGet.Config SpacetimeDB.ClientSDK.sln - - name: Run .NET tests + - name: Run C# SDK tests working-directory: sdks/csharp - run: dotnet test -warnaserror --no-restore SpacetimeDB.ClientSDK.csproj + run: dotnet test -warnaserror --no-restore tests~/tests.csproj - name: Verify C# formatting working-directory: sdks/csharp From 8e66423d16b04b246d0ac38a9e79a1536ad71a73 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Tue, 22 Sep 2026 16:20:23 -0500 Subject: [PATCH 27/49] Cache index instance --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 18 +++++ .../snapshots/Module.net10#FFI.verified.cs | 80 +++++++++++++------ .../snapshots/Module.net10#FFI.verified.cs | 12 ++- .../snapshots/Module.net10#FFI.verified.cs | 66 ++++++++++----- crates/bindings-csharp/Codegen/Module.cs | 20 ++++- modules/namespace-test-cs/Lib.cs | 8 ++ .../libraries/AuthLib/Lib.cs | 10 ++- 7 files changed, 159 insertions(+), 55 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index edde1445b8f..0ac8042a11b 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -935,6 +935,24 @@ byte[] Snapshot(object builder) => (byte[])consumerType.GetMethod("Snapshot")! var name = Assert.IsType(field.GetValue(null)); Assert.StartsWith("cached.", name); Assert.Same(name, field.GetValue(null)); + if (type.BaseType!.Name != "ReadOnlyTableView`1") + { + // Resolving a name above must not initialize a handle: this test has no host transaction. + var owner = type.DeclaringType!; + var accessor = Assert.Single(owner.GetProperties(System.Reflection.BindingFlags.Instance + | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic) + .Where(property => property.PropertyType == type)); + var instance = owner.GetField("__" + accessor.Name, System.Reflection.BindingFlags.Static + | System.Reflection.BindingFlags.NonPublic)!; + Assert.True(instance.IsPrivate); + Assert.False(instance.IsInitOnly); + Assert.Equal(type, instance.FieldType); + Assert.Null(instance.GetValue(null)); + Assert.Null(type.GetProperty("Instance", System.Reflection.BindingFlags.Static + | System.Reflection.BindingFlags.NonPublic)); + Assert.Null(type.GetField("__Instance", System.Reflection.BindingFlags.Static + | System.Reflection.BindingFlags.NonPublic)); + } } foreach (var baseName in new[] { diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs index 165867bf69a..c8e1d745a5b 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs @@ -2256,7 +2256,8 @@ internal IdentityUniqueIndex() public global::Player? Find(SpacetimeDB.Identity key) => FindSingle(key); } - public IdentityUniqueIndex Identity => new(); + private static IdentityUniqueIndex? __Identity; + public IdentityUniqueIndex Identity => __Identity ??= new(); } public readonly struct TestAutoIncNotInteger @@ -2393,7 +2394,8 @@ internal IdentityFieldUniqueIndex() public global::TestAutoIncNotInteger? Find(string key) => FindSingle(key); } - public IdentityFieldUniqueIndex IdentityField => new(); + private static IdentityFieldUniqueIndex? __IdentityField; + public IdentityFieldUniqueIndex IdentityField => __IdentityField ??= new(); } public readonly struct TestDefaultFieldValues @@ -2678,7 +2680,9 @@ public sealed class TestIndexWithoutColumnsIndex() static TestIndexWithoutColumnsIndex() { } } - public TestIndexWithoutColumnsIndex TestIndexWithoutColumns => new(); + private static TestIndexWithoutColumnsIndex? __TestIndexWithoutColumns; + public TestIndexWithoutColumnsIndex TestIndexWithoutColumns => + __TestIndexWithoutColumns ??= new(); public sealed class TestIndexWithEmptyColumnsIndex() : SpacetimeDB.Internal.IndexBase(__resolvedName) @@ -2693,7 +2697,9 @@ public sealed class TestIndexWithEmptyColumnsIndex() static TestIndexWithEmptyColumnsIndex() { } } - public TestIndexWithEmptyColumnsIndex TestIndexWithEmptyColumns => new(); + private static TestIndexWithEmptyColumnsIndex? __TestIndexWithEmptyColumns; + public TestIndexWithEmptyColumnsIndex TestIndexWithEmptyColumns => + __TestIndexWithEmptyColumns ??= new(); public sealed class TestUnknownColumnsIndex() : SpacetimeDB.Internal.IndexBase(__resolvedName) @@ -2708,7 +2714,8 @@ public sealed class TestUnknownColumnsIndex() static TestUnknownColumnsIndex() { } } - public TestUnknownColumnsIndex TestUnknownColumns => new(); + private static TestUnknownColumnsIndex? __TestUnknownColumns; + public TestUnknownColumnsIndex TestUnknownColumns => __TestUnknownColumns ??= new(); public sealed class SelfIndexingColumnIndex() : SpacetimeDB.Internal.IndexBase(__resolvedName) @@ -2753,7 +2760,8 @@ public ulong Delete(global::SpacetimeDB.Bound SelfIndexingColumn) => ); } - public SelfIndexingColumnIndex SelfIndexingColumn => new(); + private static SelfIndexingColumnIndex? __SelfIndexingColumn; + public SelfIndexingColumnIndex SelfIndexingColumn => __SelfIndexingColumn ??= new(); public sealed class SecondaryIndexingColumnIndex() : SpacetimeDB.Internal.IndexBase(__resolvedName) @@ -2798,7 +2806,9 @@ public ulong Delete(global::SpacetimeDB.Bound SecondaryIndexingColumn) => ); } - public SecondaryIndexingColumnIndex SecondaryIndexingColumn => new(); + private static SecondaryIndexingColumnIndex? __SecondaryIndexingColumn; + public SecondaryIndexingColumnIndex SecondaryIndexingColumn => + __SecondaryIndexingColumn ??= new(); public sealed class TestUnexpectedColumnsIndex() : SpacetimeDB.Internal.IndexBase(__resolvedName) @@ -2843,7 +2853,9 @@ public ulong Delete(global::SpacetimeDB.Bound SelfIndexingColumn) => ); } - public TestUnexpectedColumnsIndex TestUnexpectedColumns => new(); + private static TestUnexpectedColumnsIndex? __TestUnexpectedColumns; + public TestUnexpectedColumnsIndex TestUnexpectedColumns => + __TestUnexpectedColumns ??= new(); } public readonly struct TestScheduleWithMissingScheduleAtField @@ -3119,7 +3131,8 @@ internal IdCorrectTypeUniqueIndex() DoUpdate(row); } - public IdCorrectTypeUniqueIndex IdCorrectType => new(); + private static IdCorrectTypeUniqueIndex? __IdCorrectType; + public IdCorrectTypeUniqueIndex IdCorrectType => __IdCorrectType ??= new(); } public readonly struct TestScheduleWithWrongPrimaryKeyType @@ -3243,7 +3256,8 @@ internal IdWrongTypeUniqueIndex() DoUpdate(row); } - public IdWrongTypeUniqueIndex IdWrongType => new(); + private static IdWrongTypeUniqueIndex? __IdWrongType; + public IdWrongTypeUniqueIndex IdWrongType => __IdWrongType ??= new(); } public readonly struct TestScheduleWithWrongScheduleAtType @@ -3367,7 +3381,8 @@ internal IdCorrectTypeUniqueIndex() DoUpdate(row); } - public IdCorrectTypeUniqueIndex IdCorrectType => new(); + private static IdCorrectTypeUniqueIndex? __IdCorrectType; + public IdCorrectTypeUniqueIndex IdCorrectType => __IdCorrectType ??= new(); } public readonly struct TestUniqueNotEquatable @@ -3497,7 +3512,8 @@ internal PrimaryKeyFieldUniqueIndex() DoUpdate(row); } - public PrimaryKeyFieldUniqueIndex PrimaryKeyField => new(); + private static PrimaryKeyFieldUniqueIndex? __PrimaryKeyField; + public PrimaryKeyFieldUniqueIndex PrimaryKeyField => __PrimaryKeyField ??= new(); } } @@ -4279,7 +4295,8 @@ internal IdentityIndex() public global::Player? Find(SpacetimeDB.Identity key) => FindSingle(key); } - public IdentityIndex Identity => new(); + private static IdentityIndex? __Identity; + public IdentityIndex Identity => __Identity ??= new(); } public sealed class TestAutoIncNotIntegerReadOnly @@ -4328,7 +4345,8 @@ internal IdentityFieldIndex() public global::TestAutoIncNotInteger? Find(string key) => FindSingle(key); } - public IdentityFieldIndex IdentityField => new(); + private static IdentityFieldIndex? __IdentityField; + public IdentityFieldIndex IdentityField => __IdentityField ??= new(); } public sealed class TestDefaultFieldValuesReadOnly @@ -4418,7 +4436,9 @@ internal TestIndexWithoutColumnsIndex() : base(__resolvedName) { } } - public TestIndexWithoutColumnsIndex TestIndexWithoutColumns => new(); + private static TestIndexWithoutColumnsIndex? __TestIndexWithoutColumns; + public TestIndexWithoutColumnsIndex TestIndexWithoutColumns => + __TestIndexWithoutColumns ??= new(); public sealed class TestIndexWithEmptyColumnsIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase @@ -4436,7 +4456,9 @@ internal TestIndexWithEmptyColumnsIndex() : base(__resolvedName) { } } - public TestIndexWithEmptyColumnsIndex TestIndexWithEmptyColumns => new(); + private static TestIndexWithEmptyColumnsIndex? __TestIndexWithEmptyColumns; + public TestIndexWithEmptyColumnsIndex TestIndexWithEmptyColumns => + __TestIndexWithEmptyColumns ??= new(); public sealed class TestUnknownColumnsIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase @@ -4454,7 +4476,8 @@ internal TestUnknownColumnsIndex() : base(__resolvedName) { } } - public TestUnknownColumnsIndex TestUnknownColumns => new(); + private static TestUnknownColumnsIndex? __TestUnknownColumns; + public TestUnknownColumnsIndex TestUnknownColumns => __TestUnknownColumns ??= new(); public sealed class SelfIndexingColumnIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase @@ -4488,7 +4511,8 @@ internal SelfIndexingColumnIndex() ); } - public SelfIndexingColumnIndex SelfIndexingColumn => new(); + private static SelfIndexingColumnIndex? __SelfIndexingColumn; + public SelfIndexingColumnIndex SelfIndexingColumn => __SelfIndexingColumn ??= new(); public sealed class SecondaryIndexingColumnIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase @@ -4522,7 +4546,9 @@ internal SecondaryIndexingColumnIndex() ); } - public SecondaryIndexingColumnIndex SecondaryIndexingColumn => new(); + private static SecondaryIndexingColumnIndex? __SecondaryIndexingColumn; + public SecondaryIndexingColumnIndex SecondaryIndexingColumn => + __SecondaryIndexingColumn ??= new(); public sealed class TestUnexpectedColumnsIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase @@ -4556,7 +4582,9 @@ internal TestUnexpectedColumnsIndex() ); } - public TestUnexpectedColumnsIndex TestUnexpectedColumns => new(); + private static TestUnexpectedColumnsIndex? __TestUnexpectedColumns; + public TestUnexpectedColumnsIndex TestUnexpectedColumns => + __TestUnexpectedColumns ??= new(); } public sealed class TestScheduleWithMissingScheduleAtFieldReadOnly @@ -4653,7 +4681,8 @@ internal IdCorrectTypeIndex() public global::TestScheduleIssues? Find(int key) => FindSingle(key); } - public IdCorrectTypeIndex IdCorrectType => new(); + private static IdCorrectTypeIndex? __IdCorrectType; + public IdCorrectTypeIndex IdCorrectType => __IdCorrectType ??= new(); } public sealed class TestScheduleWithWrongPrimaryKeyTypeReadOnly @@ -4702,7 +4731,8 @@ internal IdWrongTypeIndex() public global::TestScheduleIssues? Find(string key) => FindSingle(key); } - public IdWrongTypeIndex IdWrongType => new(); + private static IdWrongTypeIndex? __IdWrongType; + public IdWrongTypeIndex IdWrongType => __IdWrongType ??= new(); } public sealed class TestScheduleWithWrongScheduleAtTypeReadOnly @@ -4751,7 +4781,8 @@ internal IdCorrectTypeIndex() public global::TestScheduleIssues? Find(int key) => FindSingle(key); } - public IdCorrectTypeIndex IdCorrectType => new(); + private static IdCorrectTypeIndex? __IdCorrectType; + public IdCorrectTypeIndex IdCorrectType => __IdCorrectType ??= new(); } public sealed class TestUniqueNotEquatableReadOnly @@ -4801,7 +4832,8 @@ internal PrimaryKeyFieldIndex() FindSingle(key); } - public PrimaryKeyFieldIndex PrimaryKeyField => new(); + private static PrimaryKeyFieldIndex? __PrimaryKeyField; + public PrimaryKeyFieldIndex PrimaryKeyField => __PrimaryKeyField ??= new(); } } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs index 0a181cf0dde..d52efae243a 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs @@ -632,7 +632,8 @@ internal IdUniqueIndex() public global::DemoTable Update(global::DemoTable row) => DoUpdate(row); } - public IdUniqueIndex Id => new(); + private static IdUniqueIndex? __Id; + public IdUniqueIndex Id => __Id ??= new(); public sealed class ByIdIndex() : SpacetimeDB.Internal.IndexBase(__resolvedName) @@ -659,7 +660,8 @@ public ulong Delete(global::SpacetimeDB.Bound Id) => DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(Id)); } - public ByIdIndex ById => new(); + private static ByIdIndex? __ById; + public ByIdIndex ById => __ById ??= new(); } } @@ -753,7 +755,8 @@ internal IdIndex() public global::DemoTable? Find(int key) => FindSingle(key); } - public IdIndex Id => new(); + private static IdIndex? __Id; + public IdIndex Id => __Id ??= new(); public sealed class ByIdIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase @@ -785,7 +788,8 @@ internal ByIdIndex() ); } - public ByIdIndex ById => new(); + private static ByIdIndex? __ById; + public ByIdIndex ById => __ById ??= new(); } } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs index ed901de7a04..8aa87cfefbe 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs @@ -1896,7 +1896,8 @@ public ulong Delete((uint X, uint Y, global::SpacetimeDB.Bound Z) f) => ); } - internal LocationIndex Location => new(); + private static LocationIndex? __Location; + internal LocationIndex Location => __Location ??= new(); } internal readonly struct BTreeViews @@ -2007,7 +2008,8 @@ internal IdUniqueIndex() public global::BTreeViews Update(global::BTreeViews row) => DoUpdate(row); } - internal IdUniqueIndex Id => new(); + private static IdUniqueIndex? __Id; + internal IdUniqueIndex Id => __Id ??= new(); internal sealed class LocationIndex() : SpacetimeDB.Internal.IndexBase(__resolvedName) @@ -2076,7 +2078,8 @@ public ulong Delete((uint X, global::SpacetimeDB.Bound Y) f) => ); } - internal LocationIndex Location => new(); + private static LocationIndex? __Location; + internal LocationIndex Location => __Location ??= new(); internal sealed class FactionIndex() : SpacetimeDB.Internal.IndexBase(__resolvedName) @@ -2121,7 +2124,8 @@ public ulong Delete(global::SpacetimeDB.Bound Faction) => ); } - internal FactionIndex Faction => new(); + private static FactionIndex? __Faction; + internal FactionIndex Faction => __Faction ??= new(); } public readonly struct MultiTable1 @@ -2241,7 +2245,8 @@ internal FooUniqueIndex() public global::MultiTableRow Update(global::MultiTableRow row) => DoUpdate(row); } - public FooUniqueIndex Foo => new(); + private static FooUniqueIndex? __Foo; + public FooUniqueIndex Foo => __Foo ??= new(); public sealed class NameIndex() : SpacetimeDB.Internal.IndexBase(__resolvedName) @@ -2286,7 +2291,8 @@ public ulong Delete(global::SpacetimeDB.Bound Name) => ); } - public NameIndex Name => new(); + private static NameIndex? __Name; + public NameIndex Name => __Name ??= new(); } public readonly struct MultiTable2 @@ -2399,7 +2405,8 @@ internal BarUniqueIndex() public global::MultiTableRow? Find(uint key) => FindSingle(key); } - public BarUniqueIndex Bar => new(); + private static BarUniqueIndex? __Bar; + public BarUniqueIndex Bar => __Bar ??= new(); } public readonly struct PrivateTable @@ -2572,7 +2579,8 @@ internal IdUniqueIndex() public global::PublicTable Update(global::PublicTable row) => DoUpdate(row); } - public IdUniqueIndex Id => new(); + private static IdUniqueIndex? __Id; + public IdUniqueIndex Id => __Id ??= new(); } internal readonly struct RegressionMultipleUniqueIndexesHadSameName @@ -2703,7 +2711,8 @@ internal Unique1UniqueIndex() FindSingle(key); } - internal Unique1UniqueIndex Unique1 => new(); + private static Unique1UniqueIndex? __Unique1; + internal Unique1UniqueIndex Unique1 => __Unique1 ??= new(); internal sealed class Unique2UniqueIndex : global::SpacetimeDB.Internal.UniqueIndex< @@ -2732,7 +2741,8 @@ internal Unique2UniqueIndex() FindSingle(key); } - internal Unique2UniqueIndex Unique2 => new(); + private static Unique2UniqueIndex? __Unique2; + internal Unique2UniqueIndex Unique2 => __Unique2 ??= new(); } public readonly struct SendMessageTimer @@ -2863,7 +2873,8 @@ internal ScheduledIdUniqueIndex() DoUpdate(row); } - public ScheduledIdUniqueIndex ScheduledId => new(); + private static ScheduledIdUniqueIndex? __ScheduledId; + public ScheduledIdUniqueIndex ScheduledId => __ScheduledId ??= new(); } } @@ -3108,7 +3119,8 @@ internal LocationIndex() ); } - internal LocationIndex Location => new(); + private static LocationIndex? __Location; + internal LocationIndex Location => __Location ??= new(); } internal sealed class BTreeViewsReadOnly @@ -3157,7 +3169,8 @@ internal IdIndex() public global::BTreeViews? Find(SpacetimeDB.Identity key) => FindSingle(key); } - public IdIndex Id => new(); + private static IdIndex? __Id; + public IdIndex Id => __Id ??= new(); public sealed class LocationIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase @@ -3211,7 +3224,8 @@ internal LocationIndex() ); } - internal LocationIndex Location => new(); + private static LocationIndex? __Location; + internal LocationIndex Location => __Location ??= new(); public sealed class FactionIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase @@ -3247,7 +3261,8 @@ internal FactionIndex() ); } - internal FactionIndex Faction => new(); + private static FactionIndex? __Faction; + internal FactionIndex Faction => __Faction ??= new(); } public sealed class MultiTable1ReadOnly @@ -3296,7 +3311,8 @@ internal FooIndex() public global::MultiTableRow? Find(uint key) => FindSingle(key); } - public FooIndex Foo => new(); + private static FooIndex? __Foo; + public FooIndex Foo => __Foo ??= new(); public sealed class NameIndex : global::SpacetimeDB.Internal.ReadOnlyIndexBase @@ -3332,7 +3348,8 @@ internal NameIndex() ); } - public NameIndex Name => new(); + private static NameIndex? __Name; + public NameIndex Name => __Name ??= new(); } public sealed class MultiTable2ReadOnly @@ -3381,7 +3398,8 @@ internal BarIndex() public global::MultiTableRow? Find(uint key) => FindSingle(key); } - public BarIndex Bar => new(); + private static BarIndex? __Bar; + public BarIndex Bar => __Bar ??= new(); } public sealed class PrivateTableReadOnly @@ -3454,7 +3472,8 @@ internal IdIndex() public global::PublicTable? Find(int key) => FindSingle(key); } - public IdIndex Id => new(); + private static IdIndex? __Id; + public IdIndex Id => __Id ??= new(); } internal sealed class RegressionMultipleUniqueIndexesHadSameNameReadOnly @@ -3504,7 +3523,8 @@ internal Unique1Index() FindSingle(key); } - public Unique1Index Unique1 => new(); + private static Unique1Index? __Unique1; + public Unique1Index Unique1 => __Unique1 ??= new(); public sealed class Unique2Index : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< @@ -3530,7 +3550,8 @@ internal Unique2Index() FindSingle(key); } - public Unique2Index Unique2 => new(); + private static Unique2Index? __Unique2; + public Unique2Index Unique2 => __Unique2 ??= new(); } public sealed class SendMessageTimerReadOnly @@ -3579,7 +3600,8 @@ internal ScheduledIdIndex() public global::Timers.SendMessageTimer? Find(ulong key) => FindSingle(key); } - public ScheduledIdIndex ScheduledId => new(); + private static ScheduledIdIndex? __ScheduledId; + public ScheduledIdIndex ScheduledId => __ScheduledId ??= new(); } } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 72de722e85b..b7da597660c 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -515,6 +515,16 @@ private string HandleLookupNameCache(string typeName, string localName) => share """ : ""; + private string IndexInstanceCache(string typeName, string identifier) => sharedContexts + ? $$""" + private static {{typeName}}? __{{identifier.TrimStart('@')}}; + """ + : ""; + + private string IndexInstance(string identifier) => sharedContexts + ? $"__{identifier.TrimStart('@')} ??= new()" + : "new()"; + public int? GetColumnIndex(AttributeData attrContext, string name, DiagReporter diag) { var index = Members @@ -618,7 +628,8 @@ public IEnumerable GenerateTableAccessorFilters(TableAccessor tableAcces public {{globalName}}? Find({{f.Type.Name}} key) => FindSingle(key); {{updateMethod}} } - {{vis}} {{f.Identifier}}UniqueIndex {{f.Identifier}} => new(); + {{IndexInstanceCache(f.Identifier + "UniqueIndex", f.Identifier)}} + {{vis}} {{f.Identifier}}UniqueIndex {{f.Identifier}} => {{IndexInstance(f.Identifier)}}; """; } @@ -682,7 +693,7 @@ public ulong Delete({{argsBounds}}) => """; } - yield return $"}}\n {vis} {identifierName}Index {identifierName} => new();\n"; + yield return $"}}\n {IndexInstanceCache(identifierName + "Index", identifierName)}\n {vis} {identifierName}Index {identifierName} => {IndexInstance(identifierName)};\n"; } } @@ -719,7 +730,8 @@ public sealed class {{{f.Identifier}}}Index public {{{globalName}}}? Find({{{f.Type.Name}}} key) => FindSingle(key); } - public {{{f.Identifier}}}Index {{{f.Identifier}}} => new(); + {{{IndexInstanceCache(f.Identifier + "Index", f.Identifier)}}} + public {{{f.Identifier}}}Index {{{f.Identifier}}} => {{{IndexInstance(f.Identifier)}}}; """; } @@ -786,7 +798,7 @@ public sealed class {{{identifierName}}}Index ); } - blocks.Add($"}}\n{vis} {identifierName}Index {identifierName} => new();"); + blocks.Add($"}}\n{IndexInstanceCache(identifierName + "Index", identifierName)}\n{vis} {identifierName}Index {identifierName} => {IndexInstance(identifierName)};"); yield return string.Join("\n", blocks); } } diff --git a/modules/namespace-test-cs/Lib.cs b/modules/namespace-test-cs/Lib.cs index cee2b465034..c2f33df74f8 100644 --- a/modules/namespace-test-cs/Lib.cs +++ b/modules/namespace-test-cs/Lib.cs @@ -70,6 +70,14 @@ public static void WriteProtectedRow(ReducerContext ctx, uint id, Identity owner [Reducer] public static void Exercise(ReducerContext ctx) { + if ( + !ReferenceEquals(ctx.Db.User.Id, ctx.Db.User.Id) + || !ReferenceEquals(ctx.Db.MyAuth.User.Id, ctx.Db.MyAuth.User.Id) + || !ReferenceEquals(ctx.Db.MyAuth.User.ByScore, ctx.Db.MyAuth.User.ByScore) + || ReferenceEquals(ctx.Db.User.Id, ctx.Db.MyAuth.User.Id) + || ReferenceEquals(ctx.Db.MyAuth.User.Id, ctx.Db.@class.User.Id) + ) + throw new Exception("Index handles must be reused within, but not across, table scopes."); ctx.Db.User.Insert(new User { Id = 2 }); AuthLib.Functions.Insert(ctx, 2); ctx.Db.MyAuth.User.Insert(new AuthLib.User { Id = 3, Score = 43 }); diff --git a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs index 93922014531..3c880847e6f 100644 --- a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs +++ b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs @@ -90,7 +90,15 @@ public static string ReadEnvironment(ProcedureContext ctx) => ctx.Env.Get("NAMESPACE_TEST") ?? "unset"; [View(Accessor = "Users", Public = true)] - public static User? Users(ViewContext ctx) => ctx.Db.User.Id.Find(2); + public static User? Users(ViewContext ctx) + { + if ( + !ReferenceEquals(ctx.Db.User.Id, ctx.Db.User.Id) + || !ReferenceEquals(ctx.Db.User.ByScore, ctx.Db.User.ByScore) + ) + throw new Exception("Read-only index handles must be reused."); + return ctx.Db.User.Id.Find(2); + } [View(Accessor = "AnonymousUsers", Public = true)] public static User? AnonymousUsers(AnonymousViewContext ctx) => ctx.Db.User.Id.Find(2); From 56f7626645b3f3ecacb8e337b5a10fc4c99cf606 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Tue, 22 Sep 2026 17:00:15 -0500 Subject: [PATCH 28/49] Revert regression in scans --- .../BSATN.Runtime.Tests/Tests.cs | 24 +++++++++++++++++++ .../BSATN.Runtime/BSATN/Runtime.cs | 4 ++++ 2 files changed, 28 insertions(+) diff --git a/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs b/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs index 703ff5a5b83..8666ad3d5a2 100644 --- a/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs +++ b/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs @@ -386,6 +386,30 @@ public static void GeneratedProductRoundTrip() ); } + [Fact] + public static void StructuralReadProductRoundTrip() + { + GenBasic.Sample( + value => + { + var row = new BasicDataClass(value); + using var stream = new MemoryStream(IStructuralReadWrite.ToBytes(row)); + using var reader = new BinaryReader(stream); + Assert.Equal(row, IStructuralReadWrite.Read(reader)); + Assert.Equal(stream.Length, stream.Position); + + stream.Position = 0; + Assert.Equal(new BasicDataStruct(value), IStructuralReadWrite.Read(reader)); + Assert.Equal(stream.Length, stream.Position); + + stream.Position = 0; + Assert.Equal(new BasicDataRecord(value), IStructuralReadWrite.Read(reader)); + Assert.Equal(stream.Length, stream.Position); + }, + iter: 10_000 + ); + } + [Fact] public static void GeneratedProductEqualsWorks() { diff --git a/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs b/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs index e7519e22765..e38d1337713 100644 --- a/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs +++ b/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs @@ -56,6 +56,10 @@ public interface IStructuralReadWrite /// /// /// +#if NET10_0_OR_GREATER + // Avoid an extra per-row call in NativeAOT scan iterators. + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif static T Read(BinaryReader reader) where T : IStructuralReadWrite, new() { From 33feb8e115b295b8f295ed43b176c15d57cab923 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Wed, 23 Sep 2026 09:25:56 -0500 Subject: [PATCH 29/49] Add more checks to avoid name collisions --- crates/bindings-csharp/BSATN.Codegen/Type.cs | 2 +- crates/bindings-csharp/Codegen.Tests/Tests.cs | 63 ++++++++++++++++ crates/bindings-csharp/Codegen/Diag.cs | 8 ++ .../bindings-csharp/Codegen/GeneratedNames.cs | 26 +++++++ crates/bindings-csharp/Codegen/Module.cs | 73 +++++++++++++++++++ .../Codegen/NamespaceDeclaration.cs | 2 + 6 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 crates/bindings-csharp/Codegen/GeneratedNames.cs diff --git a/crates/bindings-csharp/BSATN.Codegen/Type.cs b/crates/bindings-csharp/BSATN.Codegen/Type.cs index 537c1c9f2dc..ff0e4899ec5 100644 --- a/crates/bindings-csharp/BSATN.Codegen/Type.cs +++ b/crates/bindings-csharp/BSATN.Codegen/Type.cs @@ -470,7 +470,7 @@ INamedTypeSymbol type typeSyntax .Members.OfType() .SelectMany(f => f.Declaration.Variables) - .Select(v => type.GetMembers(v.Identifier.Text).OfType().Single()) + .Select(v => type.GetMembers(v.Identifier.ValueText).OfType().Single()) .Where(f => !f.IsStatic); public static IFieldSymbol? FindSpacetimeDbField(ITypeSymbol rowType, string fieldName) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 0ac8042a11b..bcf4cb6088a 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -461,6 +461,8 @@ object[] Parsed(GeneratorDriver driver) => [.. driver.GetRunResult().Results.Sin Reject(Mount(accessor: name), "database identifier"); foreach (var name in new[] { "st", "ST", "spacetimedb", "pg_catalog", "PG_temp" }) Reject(Mount(accessor: name), "reserved"); + foreach (var name in new[] { "GetType", "ToString", "Equals", "GetHashCode" }) + Reject(Mount(accessor: name), "receiver member"); foreach (var accessor in new[] { "", "a.b", "a-b", "1auth", "@class", " auth" }) Reject(Mount(accessor: accessor), "C# identifier"); Reject("[assembly: SpacetimeDB.Namespace(typeof(Auth.Marker))]", "C# identifier"); @@ -508,6 +510,67 @@ [new Module().AsSourceGenerator()], parseOptions: oldLanguage #endif } +#if NET10_0_OR_GREATER + [Fact] + public static async Task NamespaceGeneratedNameCollisions() + { + var fixture = await Fixture.Compile("server"); + (Compilation Output, ImmutableArray Diagnostics) Generate(string source) + { + var compilation = CSharpCompilation.Create( + "CollisionProof", + [CSharpSyntaxTree.ParseText("global using System; global using System.IO; global using System.Collections.Generic;\n" + source, fixture.ParseOptions)], + fixture.SampleCompilation.References, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) + ); + CSharpGeneratorDriver.Create( + [new Type().AsSourceGenerator(), new Module().AsSourceGenerator(), new EnvironmentGenerator().AsSourceGenerator()], + parseOptions: fixture.ParseOptions + ).RunGeneratorsAndUpdateCompilation(compilation, out var output, out var diagnostics); + return (output, diagnostics); + } + foreach (var (accessor, fields, symbol) in new[] + { + ("User", "[SpacetimeDB.Unique] public uint Count;", "Count"), + ("User", "[SpacetimeDB.Unique] public uint Id; [SpacetimeDB.Unique] public uint __Id;", "__Id"), + ("User", "[SpacetimeDB.Unique] public uint Id; [SpacetimeDB.Unique] public uint IdUniqueIndex;", "IdUniqueIndex"), + ("User", "public uint UserCols;", "UserCols"), + ("User", "[SpacetimeDB.PrimaryKey] public uint UserIxCols;", "UserIxCols"), + ("Tables", "public uint Id;", "Tables"), + ("ReadOnlyTables", "public uint Id;", "ReadOnlyTables"), + ("Queries", "public uint Id;", "Queries"), + ("GetType", "public uint Id;", "GetType"), + }) + { + var (_, diagnostics) = Generate($$""" + [SpacetimeDB.Table(Accessor = "{{accessor}}")] + public partial struct Row { {{fields}} } + """); + Assert.DoesNotContain(diagnostics, d => d.Id == "CS8785"); + Assert.True(diagnostics.Any(d => d.GetMessage().Contains("Generated C# name") + && d.GetMessage().Contains(symbol) && d.Location.IsInSource), + $"Expected collision for {accessor}.{symbol}: {string.Join("\n", diagnostics)}"); + } + var (_, crossTableDiagnostics) = Generate(""" + [SpacetimeDB.Table(Accessor = "User")] + [SpacetimeDB.Table(Accessor = "UserIx")] + public partial struct Row { public uint Id; } + """); + Assert.Contains(crossTableDiagnostics, d => d.GetMessage().Contains("UserIxCols") + && d.GetMessage().Contains("table 'User'") && d.GetMessage().Contains("table 'UserIx'")); + + var (valid, validDiagnostics) = Generate(""" + [SpacetimeDB.Table(Accessor = "First")] + [SpacetimeDB.Table(Accessor = "Second")] + public partial struct Row { [SpacetimeDB.Unique] public uint @class; } + """); + Assert.Empty(validDiagnostics.Where(d => d.Severity == DiagnosticSeverity.Error)); + using var dll = new MemoryStream(); + var emitted = valid.Emit(dll); + Assert.True(emitted.Success, string.Join("\n", emitted.Diagnostics)); + } +#endif + [Fact] public static async Task TypeGeneratorOnClient() { diff --git a/crates/bindings-csharp/Codegen/Diag.cs b/crates/bindings-csharp/Codegen/Diag.cs index d98bfc99e35..5b54173166f 100644 --- a/crates/bindings-csharp/Codegen/Diag.cs +++ b/crates/bindings-csharp/Codegen/Diag.cs @@ -392,4 +392,12 @@ string type ctx => $"Dependency '{ctx.assembly}' mounted in namespace '{ctx.name}' declares lifecycle reducers: {ctx.reducers}. Lifecycle reducers are only supported in the root scope; remove them or omit the dependency's namespace declaration so it registers automatically in public.", _ => Location.None ); + + public static readonly ErrorDescriptor<(Location location, string scope, string name, string first, string second)> GeneratedNameCollision = + new( + group, + "Conflicting generated C# names", + ctx => $"Generated C# name '{ctx.scope}.{ctx.name}' is used by both {ctx.first} and {ctx.second}. Choose distinct accessors or member names.", + ctx => ctx.location + ); } diff --git a/crates/bindings-csharp/Codegen/GeneratedNames.cs b/crates/bindings-csharp/Codegen/GeneratedNames.cs new file mode 100644 index 00000000000..5ae6c609592 --- /dev/null +++ b/crates/bindings-csharp/Codegen/GeneratedNames.cs @@ -0,0 +1,26 @@ +namespace SpacetimeDB.Codegen; + +using Microsoft.CodeAnalysis.CSharp; + +internal delegate void GeneratedNameCollisionReporter( + string scope, + string name, + string firstContributor, + string secondContributor +); + +// Compare symbols in their emitted C# scope; @ escaping does not distinguish names. +sealed class GeneratedNames(GeneratedNameCollisionReporter report) +{ + private readonly Dictionary<(string Scope, string Name), string> declarations = []; + + internal void Add(string scope, string identifier, string contributor) + { + var name = SyntaxFactory.ParseToken(identifier).ValueText; + var key = (scope, name); + if (declarations.TryGetValue(key, out var previous)) + report(scope, name, previous, contributor); + else + declarations.Add(key, contributor); + } +} diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index b7da597660c..7e47e5fca2a 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -590,6 +590,66 @@ public TableDeclaration(GeneratorAttributeSyntaxContext context, DiagReporter di .Select(a => new TableIndex(this, a, diag)) .ToImmutableArray() ); + if (sharedContexts) + ValidateGeneratedNames(diag, typeSyntax.GetLocation()); + } + + private void ValidateGeneratedNames(DiagReporter diag, Location location) + { + var names = new GeneratedNames((scope, name, first, second) => + diag.Report(ErrorDescriptor.GeneratedNameCollision, (location, scope, name, first, second))); + foreach (var table in TableAccessors) + { + var owner = $"table '{table.Name}' on '{FullName}'"; + var writable = $"{TableHandlesNamespace}.{table.Name}"; + var readOnly = $"{ViewHandlesNamespace}.{table.Name}ReadOnly"; + names.Add(writable, table.Identifier, "enclosing table handle"); + names.Add(readOnly, table.Identifier + "ReadOnly", "enclosing read-only handle"); + foreach (var member in new[] { "LookupName", "ReadGenFields", "MakeTableDesc", "MakeScheduleDesc", "Count", "Iter", "Insert", "Delete", "Clear" }) + names.Add(writable, member, "generated table member"); + foreach (var member in new[] { "__resolvedName", "Count", "Iter" }) + names.Add(readOnly, member, "generated read-only table member"); + + void Index(string identifier, bool unique, string contributor) + { + foreach (var scope in new[] { writable, readOnly }) + { + names.Add(scope, identifier, contributor); + names.Add(scope, "__" + identifier.TrimStart('@'), $"cache field for {contributor}"); + names.Add(scope, identifier + (unique && scope == writable ? "UniqueIndex" : "Index"), + $"index type for {contributor}"); + } + } + foreach (var constraint in GetConstraints(table, ColumnAttrs.Unique).Where(c => c.Col.IsEquatable)) + Index(constraint.Col.Identifier, true, $"unique column '{constraint.Col.Name}' of {owner}"); + foreach (var index in GetIndexes(table).Where(i => i.AccessorName.Length != 0)) + Index(index.AccessorIdentifier, false, $"index '{index.AccessorName}' of {owner}"); + + foreach (var container in new[] { "Tables", "ReadOnlyTables", "Queries" }) + if (table.Name == container) + names.Add(container, container, "enclosing descriptor container"); + foreach (var container in new[] { "Tables", "ReadOnlyTables", "Queries" }) + names.Add(container, table.Identifier, owner); + if (table.Name is "GetType" or "ToString" or "Equals" or "GetHashCode") + diag.Report(ErrorDescriptor.GeneratedNameCollision, + (location, "context database/query receiver", table.Name, "existing receiver member", owner)); + var cols = table.Identifier + "Cols"; + names.Add(cols, cols, "enclosing query columns type"); + foreach (var column in Members) + names.Add(cols, column.Identifier, $"column '{column.Name}' of {owner}"); + var ixCols = table.Identifier + "IxCols"; + names.Add(ixCols, ixCols, "enclosing indexed query columns type"); + var indexedPositions = new HashSet( + GetConstraints(table, ColumnAttrs.PrimaryKey | ColumnAttrs.Unique).Select(c => c.Pos)); + foreach (var index in GetIndexes(table)) + foreach (var column in index.Columns.Array) + indexedPositions.Add(column.Index); + foreach (var position in indexedPositions) + { + var column = Members[position]; + names.Add(ixCols, column.Identifier, $"indexed column '{column.Name}' of {owner}"); + } + } } protected override ColumnDeclaration ConvertMember( @@ -2744,6 +2804,19 @@ string GenerateDispatchRouting(string category, string arguments, string unknown columnDefaultValues ) = inputs; + if (sharedContexts) + { + var generatedNames = new GeneratedNames((scope, name, first, second) => + context.ReportDiagnostic(ErrorDescriptor.GeneratedNameCollision.ToDiag( + (Location.None, scope, name, first, second)))); + foreach (var table in tableAccessors) + { + var owner = $"table '{table.TableAccessorName}' on '{table.TableName}'"; + generatedNames.Add(extensionNamespaceName, EscapeIdentifier(table.TableAccessorName + "Cols"), owner); + generatedNames.Add(extensionNamespaceName, EscapeIdentifier(table.TableAccessorName + "IxCols"), owner); + } + } + string ConsumerAccessors(string container) { var members = new List(); diff --git a/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs b/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs index 7937d8fbb00..406fc0b3ef6 100644 --- a/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs +++ b/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs @@ -128,6 +128,8 @@ void CheckDuplicate(Dictionary seen, string key, string m ); if (tables.Contains(accessor)) Error($"Namespace accessor '{accessor}' conflicts with a root table accessor."); + if (accessor is "GetType" or "ToString" or "Equals" or "GetHashCode") + Error($"Namespace accessor '{accessor}' conflicts with an existing context database/query receiver member."); if (valid) result.Add(new(identity, accessor)); From c65452d2a0c9dee7cfe3d357708938db16678cc9 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Wed, 23 Sep 2026 11:28:48 -0500 Subject: [PATCH 30/49] Clean testing suite --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 645 +----------------- crates/codegen/tests/codegen.rs | 130 +--- .../tests/csharp-namespaces/Program.cs | 190 ------ crates/testing/tests/environment.rs | 176 ++++- .../tests/standalone_integration_test.rs | 111 --- modules/namespace-environment-test-cs/Lib.cs | 57 ++ .../namespace-environment-test-cs/README.md | 30 + .../libraries/AuthLib/AuthLib.csproj | 11 + .../libraries/AuthLib/Lib.cs | 50 ++ .../libraries/PublicLib/Lib.cs | 21 + .../libraries/PublicLib/PublicLib.csproj | 11 + .../namespace-environment-test-cs.csproj | 12 + modules/namespace-test-cs/Lib.cs | 20 - .../libraries/AuthLib/Lib.cs | 4 - .../regression-tests/namespaces/Program.cs | 16 +- .../regression-tests/namespaces/README.md | 5 +- .../MyAuth/Procedures/ReadEnvironment.g.cs | 65 -- .../Procedures/ReadEnvironment.g.cs | 65 -- .../module_bindings/SpacetimeDBClient.g.cs | 2 +- 19 files changed, 350 insertions(+), 1271 deletions(-) delete mode 100644 crates/codegen/tests/csharp-namespaces/Program.cs create mode 100644 modules/namespace-environment-test-cs/Lib.cs create mode 100644 modules/namespace-environment-test-cs/README.md create mode 100644 modules/namespace-environment-test-cs/libraries/AuthLib/AuthLib.csproj create mode 100644 modules/namespace-environment-test-cs/libraries/AuthLib/Lib.cs create mode 100644 modules/namespace-environment-test-cs/libraries/PublicLib/Lib.cs create mode 100644 modules/namespace-environment-test-cs/libraries/PublicLib/PublicLib.csproj create mode 100644 modules/namespace-environment-test-cs/namespace-environment-test-cs.csproj delete mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadEnvironment.g.cs delete mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/ReadEnvironment.g.cs diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index bcf4cb6088a..fb506d75dbf 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -38,9 +38,9 @@ private class Fixture(string projectDir, CSharpCompilation sampleCompilation) public CSharpParseOptions ParseOptions { get; } = (CSharpParseOptions)sampleCompilation.SyntaxTrees.First().Options; - public static async Task Compile(string name, string? targetFramework = null) + public static async Task Compile(string name) { - targetFramework ??= name == "client" ? "netstandard2.1" : ModuleTargetFramework; + var targetFramework = name == "client" ? "netstandard2.1" : ModuleTargetFramework; var projectDir = Path.Combine(GetProjectDir(), "fixtures", name); using var workspace = MSBuildWorkspace.Create( new Dictionary { ["TargetFramework"] = targetFramework } @@ -255,134 +255,7 @@ static void AssertNoCs0436Diagnostics(Compilation compilation) Assert.DoesNotContain(diagnostics, d => d.Id == "CS0436"); } - [Fact] - // Make sure our existing C# module examples still compile when targeting .NET 8 (namespaces will only be supported on .NET 10) - public static async Task NamespaceProofPreservesNet8RootExamples() - { - foreach (var name in new[] { "server", "explicitnames" }) - { - var fixture = await Fixture.Compile(name, "net8.0"); - var compilation = fixture.SampleCompilation; - foreach ( - var generator in new IIncrementalGenerator[] - { - new SpacetimeDB.Codegen.Type(), - new SpacetimeDB.Codegen.Module(), - new EnvironmentGenerator(), - } - ) - { - compilation = compilation.AddSyntaxTrees( - fixture.RunGeneratorAndGetResult(generator).GeneratedTrees - ); - } - Assert.Empty(GetCompilationErrors(compilation)); - AssertContextOwnership(compilation); - } - } - - [Theory] - [InlineData("server")] - [InlineData("explicitnames")] - public static async Task FormattedGeneratedCodeCompiles(string fixtureName) - { - var fixture = await Fixture.Compile(fixtureName); - var compilation = fixture.SampleCompilation; - foreach (var generator in new IIncrementalGenerator[] { new Type(), new Module(), new EnvironmentGenerator() }) - { - foreach (var tree in fixture.RunGeneratorAndGetResult(generator).GeneratedTrees) - { - var formatted = TestInit.FormatCode(tree.ToString()); - Assert.Empty(formatted.Errors); - compilation = compilation.AddSyntaxTrees( - CSharpSyntaxTree.ParseText( - formatted.Code, - fixture.ParseOptions, - path: tree.FilePath - ) - ); - } - } - Assert.Empty(GetCompilationErrors(compilation)); - AssertContextOwnership(compilation); - } - - [Theory] - [InlineData("net8.0")] #if NET10_0_OR_GREATER - [InlineData("net10.0")] -#endif - public static async Task NamespaceImmediateSchedulesUseExplicitFunctionNames(string framework) - { - var fixture = await Fixture.Compile("server", framework); - var source = """ - global using System; - global using System.IO; - global using System.Collections.Generic; - global using System.Linq; - public static partial class Jobs - { - [SpacetimeDB.Reducer(Name = "reducer_job")] - public static void ReducerTick(SpacetimeDB.ReducerContext ctx, uint payload) { } - [SpacetimeDB.Procedure(Name = "procedure_job")] - public static void ProcedureTick(SpacetimeDB.ProcedureContext ctx, uint payload) { } - [SpacetimeDB.Reducer] - public static void DefaultReducer(SpacetimeDB.ReducerContext ctx) { } - [SpacetimeDB.Procedure] - public static void DefaultProcedure(SpacetimeDB.ProcedureContext ctx) { } - } - """; - var input = CSharpCompilation.Create( - "ScheduledLibrary", - [CSharpSyntaxTree.ParseText(source, fixture.ParseOptions)], - fixture.SampleCompilation.References, - new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) - ); - var driver = CSharpGeneratorDriver.Create( - [new Type().AsSourceGenerator(), new Module().AsSourceGenerator(), new EnvironmentGenerator().AsSourceGenerator()], - parseOptions: fixture.ParseOptions - ); - driver.RunGeneratorsAndUpdateCompilation(input, out var output, out var diagnostics); - Assert.Empty(diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error)); - Assert.Empty(GetCompilationErrors(output)); - - foreach (var (method, wireName) in new[] - { - ("ReducerTick", "reducer_job"), - ("ProcedureTick", "procedure_job"), - ("DefaultReducer", "DefaultReducer"), - ("DefaultProcedure", "DefaultProcedure"), - }) - { - var helper = Assert.Single(output.SyntaxTrees - .SelectMany(tree => tree.GetRoot().DescendantNodes()) - .OfType() - .Where(node => node.Identifier.ValueText == "VolatileNonatomicScheduleImmediate" + method)); - var call = Assert.Single(helper.DescendantNodes() - .OfType() - .Where(node => node.Expression.ToString().EndsWith(".VolatileNonatomicScheduleImmediate"))); - var name = call.ArgumentList.Arguments[0].Expression; - if (framework == "net10.0") - { - var field = Assert.IsAssignableFrom(output.GetSemanticModel(name.SyntaxTree) - .GetSymbolInfo(name).Symbol); - Assert.True(field.IsStatic); - Assert.True(field.IsReadOnly); - Assert.Contains(field.ContainingType.StaticConstructors, ctor => !ctor.IsImplicitlyDeclared); - Assert.DoesNotContain(helper.DescendantNodes().OfType(), - invocation => invocation.Expression.ToString().EndsWith(".ResolveName")); - var declaration = Assert.IsType( - Assert.Single(field.DeclaringSyntaxReferences).GetSyntax()); - var resolve = Assert.IsType(declaration.Initializer!.Value); - Assert.Equal("global::SpacetimeDB.Internal.Module.ResolveName", resolve.Expression.ToString()); - Assert.StartsWith("ScheduledLibrary,", (string)output.GetSemanticModel(resolve.SyntaxTree) - .GetConstantValue(resolve.ArgumentList.Arguments[0].Expression).Value!); - name = resolve.ArgumentList.Arguments[1].Expression; - } - Assert.Equal(wireName, output.GetSemanticModel(name.SyntaxTree).GetConstantValue(name).Value); - } - } - [Fact] public static async Task NamespaceDeclarationsParseAndValidate() { @@ -428,7 +301,6 @@ [new Module().AsSourceGenerator()], trackIncrementalGeneratorSteps: true ) ).RunGenerators(Create("Consumer", source, auth, audit)); -#if NET10_0_OR_GREATER void Reject(string source, string message) { var diagnostics = Run(source).GetRunResult().Diagnostics; @@ -439,21 +311,6 @@ void Reject(string source, string message) object[] Parsed(GeneratorDriver driver) => [.. driver.GetRunResult().Results.Single() .TrackedSteps["SpacetimeDB.Namespace.Parse"].Single().Outputs .SelectMany(o => ((System.Collections.IEnumerable)o.Value).Cast())]; - foreach (var accessor in new[] { "MyAuth", "class", "event" }) - { - var driver = Run(Mount(accessor: accessor)); - Assert.Empty(driver.GetRunResult().Diagnostics); - var declaration = Assert.Single(Parsed(driver)); - Assert.Equal(accessor, declaration.GetType().GetProperty("Accessor")!.GetValue(declaration)); - Assert.Equal( - accessor == "MyAuth" ? accessor : "@" + accessor, - declaration.GetType().GetProperty("AccessorIdentifier")!.GetValue(declaration) - ); - Assert.Equal( - "Auth, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", - declaration.GetType().GetProperty("AssemblyIdentity")!.GetValue(declaration) - ); - } Assert.Empty(Run(Mount(accessor: new string('a', 63))).GetRunResult().Diagnostics); Assert.Empty(Run(Mount(accessor: "public")).GetRunResult().Diagnostics); Reject(Mount(accessor: new string('a', 64)), "63 UTF-8 bytes"); @@ -483,13 +340,6 @@ [new Module().AsSourceGenerator()], parseOptions: oldLanguage ).RunGenerators(oldCompilation).GetRunResult(); Assert.Contains(oldResult.Diagnostics, d => d.GetMessage().Contains("require .NET 10 and C# 14")); - // Only assembly targets are legal, independently of generator validation. - var wrongTarget = Create("Consumer", "[SpacetimeDB.Namespace(typeof(Auth.Marker))] public class Wrong { }", auth); - Assert.Contains(wrongTarget.GetDiagnostics(), d => d.Id == "CS0592"); - var obsoleteName = Create("Consumer", - "[assembly: SpacetimeDB.Namespace(typeof(Auth.Marker), Accessor = \"MyAuth\", Name = \"auth_data\")]", auth); - Assert.Contains(obsoleteName.GetDiagnostics(), d => d.Id == "CS0246"); - var original = Run(Mount()); foreach (var source in new[] { Mount(accessor: "Other"), Mount(accessor: "class") }) { @@ -502,15 +352,7 @@ [new Module().AsSourceGenerator()], parseOptions: oldLanguage o => o.Reason == IncrementalStepRunReason.Modified ); } -#else - var compilation = Create("Consumer", Mount(), auth, audit); - Assert.Null(compilation.GetTypeByMetadataName("SpacetimeDB.NamespaceAttribute")); - Assert.Contains(compilation.GetDiagnostics(), d => d.Id == "CS0234"); - Assert.Empty(Run(Mount()).GetRunResult().Diagnostics); -#endif } - -#if NET10_0_OR_GREATER [Fact] public static async Task NamespaceGeneratedNameCollisions() { @@ -591,7 +433,7 @@ public static async Task TypeGeneratorOnClient() [InlineData(true, true)] public static async Task NamespaceDependenciesRegisterOnceInStableOrder(bool rootHasTable, bool mounted) { - var fixture = await Fixture.Compile("server", "net10.0"); + var fixture = await Fixture.Compile("server"); const string usings = "global using System; global using System.IO; " + "global using System.Collections.Generic; global using System.Linq;\n"; CSharpCompilation Create(string name, string source, params MetadataReference[] references) => @@ -624,9 +466,6 @@ namespace {{name}} { public class Sentinel { } [SpacetimeDB.Table] public partial struct {{name}}Row { public uint Id; } - public static class QueryHelpers { - public static SpacetimeDB.IQuery<{{name}}Row> Query(SpacetimeDB.AnonymousViewContext ctx) => ctx.From.{{name}}Row().Where(c => c.Id.Eq(SpacetimeDB.SqlLit.Int(1u))); - } } """; string Descriptor(CSharpCompilation compilation) => Assert.Single( @@ -654,19 +493,9 @@ MethodDeclarationSyntax Method(CSharpCompilation compilation, string name) => As if (mounted) rootSource = "[assembly: SpacetimeDB.Namespace(typeof(Alpha.Sentinel), Accessor = \"Auth\")]\n" + "[assembly: SpacetimeDB.Namespace(typeof(Beta.Sentinel), Accessor = \"class\")]\n" - + rootSource - + "public static class Helpers { public static ulong Count(SpacetimeDB.ReducerContext ctx) => ctx.Db.Auth.AlphaRow.Count + ctx.Db.@class.BetaRow.Count + ctx.Db.SharedRow.Count; }"; - rootSource += $$""" - public static class RootQueries { - public static SpacetimeDB.IQuery Alpha(SpacetimeDB.ViewContext ctx) => ctx.From.{{(mounted ? "Auth." : "")}}AlphaRow(); - public static SpacetimeDB.IQuery Beta(SpacetimeDB.AnonymousViewContext ctx) => ctx.From.{{(mounted ? "@class." : "")}}BetaRow(); - public static SpacetimeDB.IQuery Shared(SpacetimeDB.ViewContext ctx) => ctx.From.SharedRow(); - } - """; + + rootSource; var root = Generate(Create("Root", rootSource, beta, utility, shared, alpha)); var reordered = Generate(Create("Root", rootSource, alpha, shared, utility, beta)); - Emit(root); - Emit(reordered); string[] Calls(CSharpCompilation compilation) => [.. Method(compilation, "Initialize").DescendantNodes() @@ -685,41 +514,12 @@ [.. Method(compilation, "Initialize").DescendantNodes() .Where(call => call.Expression.ToString().EndsWith(".RegisterSubmodule")).ToArray(); Assert.Equal(["\"Auth\"", "\"class\""], submodules.Select(call => call.ArgumentList.Arguments[0].ToString())); - var invalid = root.AddSyntaxTrees(CSharpSyntaxTree.ParseText( - "public static class BadView { public static void Write(SpacetimeDB.ViewContext ctx) => ctx.Db.Auth.AlphaRow.Insert(new Alpha.AlphaRow()); }", - fixture.ParseOptions)); - Assert.Contains(GetCompilationErrors(invalid), d => d.Id == "CS1061"); } Assert.Equal(expected, Calls(root)); Assert.Equal(expected, Calls(reordered)); - foreach (var (export, category) in new[] - { - ("__call_reducer__", "Reducer"), - ("__call_procedure__", "Procedure"), - ("__call_http_handler__", "HttpHandler"), - ("__call_view__", "View"), - ("__call_view_anon__", "AnonymousView"), - }) - { - var body = Method(root, export).Body!; - var routes = body.DescendantNodes().OfType() - .Where(call => call.Expression is MemberAccessExpressionSyntax member - && member.Name.Identifier.ValueText == "CallLocal" + category).ToArray(); - Assert.Equal(expected.Select(name => name.Replace(".Register", ".CallLocal" + category)), - routes.Select(call => call.Expression.ToString())); - Assert.All(routes, call => Assert.Equal("localId", - call.ArgumentList.Arguments[0].Expression.ToString())); - var offsets = body.DescendantNodes().OfType() - .Where(assignment => assignment.IsKind(SyntaxKind.SubtractAssignmentExpression)); - Assert.Equal(expected.Select(name => name.Replace(".Register", "." + category + "Count")), - offsets.Select(assignment => assignment.Right.ToString())); - var negativeGuard = Assert.IsType(body.Statements[0]); - Assert.Equal("id < 0", negativeGuard.Condition.ToString()); - Assert.Equal(Method(root, export).ToString(), Method(reordered, export).ToString()); - } - Assert.DoesNotContain(Method(root, "Register").DescendantNodes() - .OfType(), call => - call.Expression.ToString().Contains("AssemblyDescriptor.Register")); + + if (rootHasTable || mounted) + return; // An unrelated utility alone must not cause an otherwise empty module to register. var plainUtility = Emit(Create("PlainUtility", "public class PlainUtility { }")); @@ -760,437 +560,6 @@ [new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions } } - [Fact] - // A separately compiled consumer can call the descriptor, registration populates only the supplied builder, and two builders receive identical metadata without modifying the static root. - public static async Task NamespaceDescriptorCrossAssemblyRegistration() - { - var fixture = await Fixture.Compile("server", "net10.0"); - var compilation = fixture.SampleCompilation; - foreach (var generator in new IIncrementalGenerator[] { new Type(), new Module(), new EnvironmentGenerator() }) - { - compilation = compilation.AddSyntaxTrees( - fixture.RunGeneratorAndGetResult(generator).GeneratedTrees - ); - } - using var moduleDll = new MemoryStream(); - var moduleEmit = compilation.Emit(moduleDll); - Assert.True(moduleEmit.Success, string.Join("\n", moduleEmit.Diagnostics)); - - var moduleReference = MetadataReference.CreateFromImage(moduleDll.ToArray()); - var consumer = CSharpCompilation.Create( - "DescriptorConsumer", - references: fixture.SampleCompilation.References.Append(moduleReference), - options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) - ); - var moduleAssembly = (IAssemblySymbol)consumer.GetAssemblyOrModuleSymbol(moduleReference)!; - var markerType = consumer.GetTypeByMetadataName("SpacetimeDB.ModuleDescriptorAttribute"); - Assert.NotNull(markerType); - var marker = Assert.Single(moduleAssembly.GetAttributes().Where(attribute => - SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, markerType) - )); - var argument = Assert.Single(marker.ConstructorArguments); - Assert.Equal(TypedConstantKind.Type, argument.Kind); - var descriptor = Assert.IsAssignableFrom(argument.Value); - Assert.Equal(TypeKind.Class, descriptor.TypeKind); - Assert.True(descriptor.IsStatic); - Assert.Equal(Accessibility.Public, descriptor.DeclaredAccessibility); - Assert.Equal("AssemblyDescriptor", descriptor.Name); - Assert.True(SymbolEqualityComparer.Default.Equals( - moduleAssembly, descriptor.ContainingAssembly - )); - var descriptorName = descriptor.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); - var dispatchCalls = new List(); - foreach (var category in new[] { "Reducer", "Procedure", "HttpHandler", "View", "AnonymousView" }) - { - var methodName = "CallLocal" + category; - var method = Assert.IsAssignableFrom( - Assert.Single(descriptor.GetMembers(methodName)) - ); - Assert.Equal(Accessibility.Public, method.DeclaredAccessibility); - Assert.True(method.IsStatic); - Assert.DoesNotContain(method.GetAttributes(), attribute => - attribute.AttributeClass?.Name == "UnmanagedCallersOnlyAttribute"); - var count = Assert.IsAssignableFrom( - Assert.Single(descriptor.GetMembers(category + "Count")) - ); - Assert.True(count.IsConst); - Assert.Equal(Accessibility.Public, count.DeclaredAccessibility); - var localMethod = Assert.Single(compilation.SyntaxTrees - .SelectMany(tree => tree.GetRoot().DescendantNodes()) - .OfType() - .Where(method => method.Identifier.ValueText == methodName - && method.Parent is ClassDeclarationSyntax type - && type.Identifier.ValueText == "ModuleRegistration")); - var localSwitch = Assert.IsType(localMethod.ExpressionBody!.Expression); - Assert.Equal(localSwitch.Arms.Count - 1, Assert.IsType(count.ConstantValue)); - - var parameters = string.Join(", ", method.Parameters.Select(parameter => - parameter.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) - + " " + parameter.Name)); - var arguments = string.Join(", ", method.Parameters.Select(parameter => parameter.Name)); - dispatchCalls.Add($"public static global::SpacetimeDB.Internal.Errno {methodName}({parameters})" - + $" => {descriptorName}.{methodName}({arguments});"); - } - - var consumerSource = $$""" - using System.IO; - using System.Linq; - using System.Reflection; - using SpacetimeDB.Internal; - - public static class DescriptorConsumer - { - {{string.Join("\n", dispatchCalls)}} - - public static void Register(ModuleBuilder builder) => - {{descriptorName}}.Register(builder); - - private static RawModuleDefV10 Describe(ModuleBuilder builder) => - (RawModuleDefV10)typeof(ModuleBuilder).GetMethod( - "BuildModuleDefinition", BindingFlags.Instance | BindingFlags.NonPublic - )!.Invoke(builder, null)!; - - public static byte[] Snapshot(ModuleBuilder builder) - { - using var stream = new MemoryStream(); - using var writer = new BinaryWriter(stream); - new RawModuleDefV10.BSATN().Write(writer, Describe(builder)); - return stream.ToArray(); - } - - public static string[] TableNames(ModuleBuilder builder) => - Describe(builder).Sections.OfType() - .SelectMany(section => section.Tables_) - .Select(table => table.SourceName).ToArray(); - - public static string[] ReducerNames(ModuleBuilder builder) => - Describe(builder).Sections.OfType() - .SelectMany(section => section.Reducers_) - .Select(reducer => reducer.SourceName).ToArray(); - - public static string[] EnvironmentNames(ModuleBuilder builder) => - Describe(builder).Sections.OfType() - .SelectMany(section => section.Environment_) - .Select(declaration => declaration.Name).ToArray(); - - public static bool CheckNamespaces() - { - const string first = "Library, Version=1.0.0.0"; - const string second = "Library, Version=2.0.0.0"; - var placements = new System.Collections.Generic.Dictionary - { - [first] = "auth_data", - [second] = "audit_data", - ["merged"] = "public", - [{{SymbolDisplay.FormatLiteral(moduleAssembly.Identity.ToString(), true)}}] = "cached", - }; - var registry = new NamespaceRegistry("root", placements); - placements[first] = "changed"; - if (registry.Resolve(first, "User") != "auth_data.User" - || registry.Resolve(second, "User") != "audit_data.User" - || registry.Resolve("root", "User") != "User" - || registry.Resolve("publicDependency", "User") != "User" - || registry.Resolve("merged", "User") != "User") - return false; - try { SpacetimeDB.Internal.Module.ResolveName(first, "User"); return false; } - catch (System.InvalidOperationException) { } - SpacetimeDB.Internal.Module.InstallNamespaces(registry); - if (SpacetimeDB.Internal.Module.ResolveName(first, "User") != "auth_data.User") return false; - if (SpacetimeDB.Internal.Module.ResolveSqlName(first, "User").ToString() != "\"auth_data\".\"User\"") return false; - if (registry.ResolveSqlName("publicDependency", "User").ToString() != "\"User\"") return false; - if (registry.ResolveSqlName("merged", "User").ToString() != "\"User\"") return false; - if (registry.ResolveSqlName("root", "User.With.Dot").ToString() != "\"User.With.Dot\"") return false; - try { SpacetimeDB.Internal.Module.InstallNamespaces(registry); return false; } - catch (System.InvalidOperationException) { } - try { new NamespaceRegistry(first, placements); return false; } - catch (System.ArgumentException) { } - try { new NamespaceRegistry("root", placements.Concat(placements)); return false; } - catch (System.ArgumentException) { } - return true; - } - } - """; - consumer = consumer.AddSyntaxTrees( - CSharpSyntaxTree.ParseText(consumerSource, fixture.ParseOptions) - ); - using var consumerDll = new MemoryStream(); - var consumerEmit = consumer.Emit(consumerDll); - Assert.True(consumerEmit.Success, string.Join("\n", consumerEmit.Diagnostics)); - - // Isolate the module's static root and Runtime types from other tests. - var loadContext = new System.Runtime.Loader.AssemblyLoadContext( - nameof(NamespaceDescriptorCrossAssemblyRegistration), isCollectible: true - ); - loadContext.Resolving += (_, name) => - { - if (!name.Name!.StartsWith("SpacetimeDB.")) - { - return null; - } - var reference = fixture.SampleCompilation.References.Single(r => - fixture.SampleCompilation.GetAssemblyOrModuleSymbol(r)?.Name == name.Name - ); - if (reference is CompilationReference projectReference) - { - using var implementation = new MemoryStream(); - var result = projectReference.Compilation.Emit(implementation); - Assert.True(result.Success, string.Join("\n", result.Diagnostics)); - implementation.Position = 0; - return loadContext.LoadFromStream(implementation); - } - var path = ((PortableExecutableReference)reference).FilePath!; - // Reference assemblies cannot execute; use the sibling implementation assembly. - var directory = new DirectoryInfo(Path.GetDirectoryName(path)!); - if (directory.Name is "ref" or "refint") - { - path = Path.Combine(directory.Parent!.FullName, Path.GetFileName(path)); - } - return loadContext.LoadFromAssemblyPath(path); - }; - try - { - moduleDll.Position = 0; - loadContext.LoadFromStream(moduleDll); - consumerDll.Position = 0; - var consumerType = loadContext.LoadFromStream(consumerDll) - .GetType("DescriptorConsumer", throwOnError: true)!; - var register = consumerType.GetMethod("Register")!; - var builderType = register.GetParameters()[0].ParameterType; - var first = Activator.CreateInstance(builderType)!; - var second = Activator.CreateInstance(builderType)!; - var root = builderType.Assembly.GetType("SpacetimeDB.Internal.Module")! - .GetField("RootBuilder")!.GetValue(null)!; - byte[] Snapshot(object builder) => (byte[])consumerType.GetMethod("Snapshot")! - .Invoke(null, [builder])!; - var empty = Snapshot(second); - var rootBefore = Snapshot(root); - - register.Invoke(null, [first]); - Assert.Equal(["REQUIRED", "OPTIONAL", "MODE"], (string[])consumerType.GetMethod("EnvironmentNames")! - .Invoke(null, [first])!); - Assert.Empty((string[])consumerType.GetMethod("EnvironmentNames")!.Invoke(null, [root])!); - Assert.Contains("PublicTable", (string[])consumerType.GetMethod("TableNames")! - .Invoke(null, [first])!); - Assert.Contains("InsertData", (string[])consumerType.GetMethod("ReducerNames")! - .Invoke(null, [first])!); - var registered = Snapshot(first); - Assert.False(empty.SequenceEqual(registered)); - Assert.Equal(empty, Snapshot(second)); - Assert.Equal(rootBefore, Snapshot(root)); - - register.Invoke(null, [second]); - Assert.Equal(registered, Snapshot(second)); - Assert.Equal(registered, Snapshot(first)); - Assert.Equal(rootBefore, Snapshot(root)); - - Assert.True((bool)consumerType.GetMethod("CheckNamespaces")!.Invoke(null, null)!); - - var loadedModule = loadContext.Assemblies.Single(a => a.GetName().Name == moduleAssembly.Name); - var cachedHandles = loadedModule.GetTypes() - .Select(type => (Type: type, Field: type.GetField("__resolvedName", - System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic))) - .Where(handle => handle.Field is not null).ToArray(); - Assert.NotEmpty(cachedHandles); - foreach (var (type, field) in cachedHandles) - { - Assert.True(field!.IsInitOnly); - Assert.False(type.Attributes.HasFlag(System.Reflection.TypeAttributes.BeforeFieldInit)); - var name = Assert.IsType(field.GetValue(null)); - Assert.StartsWith("cached.", name); - Assert.Same(name, field.GetValue(null)); - if (type.BaseType!.Name != "ReadOnlyTableView`1") - { - // Resolving a name above must not initialize a handle: this test has no host transaction. - var owner = type.DeclaringType!; - var accessor = Assert.Single(owner.GetProperties(System.Reflection.BindingFlags.Instance - | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic) - .Where(property => property.PropertyType == type)); - var instance = owner.GetField("__" + accessor.Name, System.Reflection.BindingFlags.Static - | System.Reflection.BindingFlags.NonPublic)!; - Assert.True(instance.IsPrivate); - Assert.False(instance.IsInitOnly); - Assert.Equal(type, instance.FieldType); - Assert.Null(instance.GetValue(null)); - Assert.Null(type.GetProperty("Instance", System.Reflection.BindingFlags.Static - | System.Reflection.BindingFlags.NonPublic)); - Assert.Null(type.GetField("__Instance", System.Reflection.BindingFlags.Static - | System.Reflection.BindingFlags.NonPublic)); - } - } - foreach (var baseName in new[] - { - "UniqueIndex`4", "IndexBase`1", - "ReadOnlyUniqueIndex`4", "ReadOnlyIndexBase`1", - "ReadOnlyTableView`1", - }) - Assert.Contains(cachedHandles, handle => handle.Type.BaseType!.Name == baseName); - - var queriesType = loadedModule.GetTypes().Single(type => - type.Name == "Queries" && type.DeclaringType?.Name == "AssemblyDescriptor"); - var queries = Activator.CreateInstance(queriesType); - var factories = queriesType.GetMethods(System.Reflection.BindingFlags.Instance - | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic - | System.Reflection.BindingFlags.DeclaredOnly); - Assert.NotEmpty(factories); - var sqlNames = new List(); - foreach (var factory in factories) - { - var cache = queriesType.DeclaringType!.GetNestedType(factory.Name + "SqlNameCache", - System.Reflection.BindingFlags.NonPublic)!; - Assert.False(cache.Attributes.HasFlag(System.Reflection.TypeAttributes.BeforeFieldInit)); - var field = cache.GetField("Name", System.Reflection.BindingFlags.Static - | System.Reflection.BindingFlags.NonPublic)!; - Assert.True(field.IsInitOnly); - var cachedName = field.GetValue(null)!; - var segments = field.FieldType.GetProperty("NamespaceSegments")!; - var firstQuery = factory.Invoke(queries, null)!; - var secondQuery = factory.Invoke(queries, null)!; - Assert.NotSame(firstQuery, secondQuery); - var nameField = factory.ReturnType.GetFields(System.Reflection.BindingFlags.Instance - | System.Reflection.BindingFlags.NonPublic).Single(f => f.FieldType == field.FieldType); - Assert.Same(segments.GetValue(cachedName), segments.GetValue(nameField.GetValue(firstQuery))); - Assert.Same(segments.GetValue(cachedName), segments.GetValue(nameField.GetValue(secondQuery))); - Assert.Equal("SELECT * FROM " + cachedName, - factory.ReturnType.GetMethod("ToSql")!.Invoke(firstQuery, null)); - Assert.StartsWith("\"cached\".", cachedName.ToString()); - sqlNames.Add(cachedName.ToString()!); - } - Assert.Equal(factories.Length, sqlNames.Distinct().Count()); - } - finally - { - loadContext.Unload(); - } - } - - [Fact] - public static async Task NamespaceEnvironmentAccessorsAreAssemblyLocal() - { - var fixture = await Fixture.Compile("server", "net10.0"); - const string usings = "global using System; global using System.IO; " - + "global using System.Linq; global using System.Collections.Generic;\n#pragma warning disable STDB_UNSTABLE\n"; - CSharpCompilation Generate(string name, string source, params MetadataReference[] references) - { - var input = CSharpCompilation.Create(name, - [CSharpSyntaxTree.ParseText(usings + source, fixture.ParseOptions)], - fixture.SampleCompilation.References.Concat(references), - new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, - nullableContextOptions: NullableContextOptions.Enable)); - var driver = CSharpGeneratorDriver.Create( - [new Type().AsSourceGenerator(), new Module().AsSourceGenerator(), new EnvironmentGenerator().AsSourceGenerator()], - parseOptions: fixture.ParseOptions); - driver.RunGeneratorsAndUpdateCompilation(input, out var output, out var diagnostics); - Assert.Empty(diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error)); - Assert.Empty(GetCompilationErrors(output)); - Assert.DoesNotContain(output.GetDiagnostics(), d => d.Id is "CS0433" or "CS0436"); - return (CSharpCompilation)output; - } - MetadataReference Emit(CSharpCompilation compilation) - { - using var dll = new MemoryStream(); - var result = compilation.Emit(dll); - Assert.True(result.Success, string.Join("\n", result.Diagnostics)); - return MetadataReference.CreateFromImage(dll.ToArray()); - } - - var contexts = new[] { "ReducerContext", "ProcedureContext", "ProcedureTxContext", - "HandlerContext", "HandlerTxContext", "ViewContext", "AnonymousViewContext" }; - var library = Generate("EnvironmentLibrary", """ - [SpacetimeDB.Env] public struct LibrarySchema { public string? SHARED; public string? LIBRARY_ONLY; } - public static class LibraryHelpers { - public static string? Read(SpacetimeDB.ReducerContext ctx) => ctx.Env.SHARED; - } - """); - // An environment-only assembly must have a descriptor so it cannot disappear from discovery. - Assert.Single(library.GetSymbolsWithName("AssemblyDescriptor", SymbolFilter.Type)); - var dependency = Emit(library); - var root = Generate("EnvironmentRoot", """ - [SpacetimeDB.Env] public struct RootSchema { public string SHARED; public string? @class; } - public static class RootHelpers { - public static string? Library(SpacetimeDB.ReducerContext ctx) => LibraryHelpers.Read(ctx); - } - """ + string.Join("\n", contexts.Select((context, index) => $$""" - public static class Context{{index}} { - public static string Read(SpacetimeDB.{{context}} ctx) => ctx.Env.SHARED; - public static string? Keyword(SpacetimeDB.{{context}} ctx) => ctx.Env.@class; - public static string? Generic(SpacetimeDB.{{context}} ctx) => ctx.Env.Get("LIBRARY_ONLY"); - } - """)), dependency); - Emit(root); - var invalid = root.AddSyntaxTrees(CSharpSyntaxTree.ParseText(""" - public static class Invalid { - public static string? Read(SpacetimeDB.ReducerContext ctx) => ctx.Env.LIBRARY_ONLY; - } - """, fixture.ParseOptions)); - Assert.Contains(GetCompilationErrors(invalid), d => d.Id == "CS1061"); - Assert.DoesNotContain(root.SyntaxTrees, tree => tree.ToString().Contains("ModuleInitializer")); - } - - [Fact] - // Can a separately compiled DLL accept our module’s contexts, and can module code still access tables through the contexts it returns? - public static async Task NamespaceContextsCrossAssemblyBoundaries() - { - var fixture = await Fixture.Compile("server"); - var contextNames = new[] - { - "ReducerContext", "ProcedureContext", "ProcedureTxContext", - "HandlerContext", "HandlerTxContext", "ViewContext", "AnonymousViewContext", - }; - var helperSource = "#pragma warning disable STDB_UNSTABLE\npublic static class ContextHelpers {" - + string.Join("\n", contextNames.Select(name => - $"public static SpacetimeDB.{name} Pass(SpacetimeDB.{name} ctx) => ctx;")) - + "}"; - var helper = CSharpCompilation.Create( - "ContextHelperLibrary", - [CSharpSyntaxTree.ParseText(helperSource, fixture.ParseOptions)], - fixture.SampleCompilation.References, - new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) - ); - using var dll = new MemoryStream(); - var emitted = helper.Emit(dll); - Assert.True(emitted.Success, string.Join("\n", emitted.Diagnostics)); - - var compilation = fixture.SampleCompilation.AddReferences( - MetadataReference.CreateFromImage(dll.ToArray()) - ); - foreach (var generator in new IIncrementalGenerator[] { new Type(), new Module(), new EnvironmentGenerator() }) - { - compilation = compilation.AddSyntaxTrees( - fixture.RunGeneratorAndGetResult(generator).GeneratedTrees - ); - } - var consumer = "#pragma warning disable STDB_UNSTABLE\n" + """ - public static class ContextConsumer - { - public static void Write(SpacetimeDB.ProcedureTxContext ctx) => - ContextHelpers.Pass(ctx).Db.PublicTable.Insert(default); - public static void Write(SpacetimeDB.HandlerTxContext ctx) => - ContextHelpers.Pass(ctx).Db.PublicTable.Insert(default); - public static ulong Read(SpacetimeDB.ViewContext ctx) => - ContextHelpers.Pass(ctx).Db.PublicTable.Count; - public static SpacetimeDB.IQuery Query(SpacetimeDB.AnonymousViewContext ctx) => - ContextHelpers.Pass(ctx).From.PublicTable(); - } - """; - consumer += "\npublic static class ContextIdentityConsumer {" - + string.Join("\n", contextNames.Select(name => - $"public static SpacetimeDB.{name} Pass(SpacetimeDB.{name} ctx) => ContextHelpers.Pass(ctx);")) - + "}"; - compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(consumer, fixture.ParseOptions)); - Assert.Empty(GetCompilationErrors(compilation)); - AssertContextOwnership(compilation); - - var invalidWrites = CSharpSyntaxTree.ParseText(""" - public static class InvalidViewWrites - { - public static void Write(SpacetimeDB.ViewContext ctx) => ctx.Db.PublicTable.Insert(default); - public static void Write(SpacetimeDB.AnonymousViewContext ctx) => ctx.Db.PublicTable.Insert(default); - } - """, fixture.ParseOptions); - var errors = GetCompilationErrors(compilation.AddSyntaxTrees(invalidWrites)).ToArray(); - Assert.Equal(2, errors.Length); - Assert.All(errors, error => Assert.Equal("CS1061", error.Id)); - } #endif [Fact] diff --git a/crates/codegen/tests/codegen.rs b/crates/codegen/tests/codegen.rs index d5aa82e43da..dcad47009a7 100644 --- a/crates/codegen/tests/codegen.rs +++ b/crates/codegen/tests/codegen.rs @@ -129,128 +129,6 @@ fn submodule_names_use_canonical_wire_names_and_accessor_paths() { ); } -fn namespace_module() -> ModuleDef { - use spacetimedb_lib::db::raw_def::v10::{ - RawModuleDefV10, RawModuleDefV10Builder, RawModuleDefV10Section, RawSubmoduleV10, - }; - use spacetimedb_lib::db::raw_def::v9::TableAccess; - use spacetimedb_lib::sats::{AlgebraicType, ProductType}; - - fn scope(value_type: AlgebraicType) -> RawModuleDefV10 { - let mut builder = RawModuleDefV10Builder::new(); - let row = builder - .build_table_with_new_type( - "User", - ProductType::from([("id", AlgebraicType::U64), ("value", value_type)]), - true, - ) - .with_primary_key(0) - .with_unique_constraint(spacetimedb_primitives::ColId(0)) - .with_index( - spacetimedb_lib::db::raw_def::v9::btree(spacetimedb_primitives::ColId(0)), - "user_id", - "Id", - ) - .finish(); - builder - .build_table_with_new_type("Secret", ProductType::from([("id", AlgebraicType::U64)]), true) - .with_access(TableAccess::Private) - .finish(); - builder - .build_table_with_new_type("Notice", ProductType::from([("id", AlgebraicType::U64)]), true) - .with_event(true) - .finish(); - builder.add_reducer("Login", ProductType::from([("user", AlgebraicType::Ref(row))])); - builder.add_procedure( - "GetUser", - ProductType::from([] as [(&str, AlgebraicType); 0]), - AlgebraicType::Ref(row), - ); - builder.add_view( - "Users", - 0, - true, - true, - ProductType::from([] as [(&str, AlgebraicType); 0]), - AlgebraicType::array(AlgebraicType::Ref(row)), - ); - let payload = builder.add_algebraic_type( - [], - "Payload", - AlgebraicType::Product(ProductType::from([("value", AlgebraicType::String)])), - true, - ); - builder.add_procedure( - "GetPayload", - ProductType::from([] as [(&str, AlgebraicType); 0]), - AlgebraicType::Ref(payload), - ); - builder.finish() - } - - let mut root = scope(AlgebraicType::Bool); - root.sections.push(RawModuleDefV10Section::Submodules(vec![ - RawSubmoduleV10 { - namespace: "MyAuth".into(), - module: scope(AlgebraicType::U32), - }, - RawSubmoduleV10 { - namespace: "class".into(), - module: scope(AlgebraicType::String), - }, - RawSubmoduleV10 { - namespace: "Empty".into(), - module: RawModuleDefV10::default(), - }, - ])); - root.try_into().expect("namespace fixture should validate") -} - -#[test] -fn csharp_namespaces_compile_and_run() { - let module = namespace_module(); - let files = generate( - &module, - &Csharp { - namespace: "Game.Bindings", - }, - &CodegenOptions::default(), - ); - let unique_names: std::collections::HashSet<_> = files.iter().map(|file| &file.filename).collect(); - assert_eq!(unique_names.len(), files.len(), "generated filenames must be unique"); - assert!(!files.iter().any(|file| file.filename.ends_with("Tables/Secret.g.cs"))); - let auth_reducer = files - .iter() - .find(|file| file.filename == "MyAuth/Reducers/Login.g.cs") - .unwrap(); - assert!(auth_reducer.code.contains("\"MyAuth.login\"")); - assert!(!auth_reducer.code.contains("MyAuth.MyAuth.")); - - let client = files - .iter() - .find(|file| file.filename == "SpacetimeDBClient.g.cs") - .unwrap(); - let child_queries: Vec<_> = client - .code - .lines() - .map(str::trim) - .filter(|line| line.starts_with("new QueryBuilder().From.@")) - .filter(|line| line.ends_with(".Notice().ToSql(),") || line.ends_with(".User().ToSql(),")) - .collect(); - assert_eq!( - child_queries, - [ - "new QueryBuilder().From.@MyAuth.Notice().ToSql(),", - "new QueryBuilder().From.@MyAuth.User().ToSql(),", - "new QueryBuilder().From.@class.Notice().ToSql(),", - "new QueryBuilder().From.@class.User().ToSql(),", - ], - "subscribe-all child tables must have stable namespace/accessor order" - ); - - compile_csharp_client(files, include_str!("csharp-namespaces/Program.cs")); -} - #[test] fn csharp_client_for_typescript_submodule_compiles_and_runs() { let typescript = compiled_typescript_module(); @@ -273,9 +151,6 @@ fn csharp_client_for_typescript_submodule_compiles_and_runs() { } fn compile_csharp_client(files: Vec, program: &str) { - // Project references share the SDK's MSBuild intermediate directory. - static COMPILE: std::sync::Mutex<()> = std::sync::Mutex::new(()); - let _guard = COMPILE.lock().unwrap_or_else(|poison| poison.into_inner()); let project = tempfile::tempdir().unwrap(); for file in files { let path = project.path().join(file.filename); @@ -306,8 +181,7 @@ fn compile_csharp_client(files: Vec, program: & ), ) .unwrap(); - static PACKED: OnceLock<()> = OnceLock::new(); - PACKED.get_or_init(|| { + { let result = std::process::Command::new("dotnet") .arg("pack") .arg(repo.join("crates/bindings-csharp/BSATN.Runtime")) @@ -321,7 +195,7 @@ fn compile_csharp_client(files: Vec, program: & String::from_utf8_lossy(&result.stdout), String::from_utf8_lossy(&result.stderr) ); - }); + } fs_err::write(project.path().join("Program.cs"), program).unwrap(); fs_err::write( project.path().join("client.csproj"), diff --git a/crates/codegen/tests/csharp-namespaces/Program.cs b/crates/codegen/tests/csharp-namespaces/Program.cs deleted file mode 100644 index cbc31761ca5..00000000000 --- a/crates/codegen/tests/csharp-namespaces/Program.cs +++ /dev/null @@ -1,190 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using Game.Bindings; -using SpacetimeDB; -using SpacetimeDB.BSATN; -using SpacetimeDB.ClientApi; -using Auth = Game.Bindings.MyAuth; -using Audit = Game.Bindings.@class; - -internal static class Program -{ - private static void Equal(T expected, T actual) - { - if (!EqualityComparer.Default.Equals(expected, actual)) - throw new Exception($"Expected {expected}, got {actual}"); - } - - private static BsatnRowList Rows(params IStructuralReadWrite[] rows) - { - using var stream = new MemoryStream(); - using var writer = new BinaryWriter(stream); - var offsets = new List(); - foreach (var row in rows) - { - offsets.Add((ulong)stream.Length); - row.WriteFields(writer); - } - return new BsatnRowList(new RowSizeHint.RowOffsets(offsets), stream.ToArray().ToList()); - } - - private static TableUpdate Change(string name, IStructuralReadWrite[] inserts, IStructuralReadWrite[] deletes) => - new TableUpdate(name, new List - { - new TableUpdateRows.PersistentTable(new PersistentTableRows(Rows(inserts), Rows(deletes))) - }); - - private static void Apply(DbConnection conn, params TableUpdate[] updates) - { - var parsed = ParsedDatabaseUpdate.New(); - foreach (var update in updates) - conn.Db.GetTable(update.TableName)!.Parse(update, parsed); - var ctx = new EventContext(conn, new Event.UnknownTransaction()); - foreach (var (table, delta) in parsed.Updates) table.PreApply(ctx, delta); - foreach (var (table, delta) in parsed.Updates) table.Apply(ctx, delta); - foreach (var (table, _) in parsed.Updates) table.PostApply(ctx); - } - - private static void Main() - { - var conn = new DbConnection(); - try - { - Check(conn); - } - finally - { - conn.Disconnect(); - } - } - - private static void CheckCachedSqlName(object value, SqlTableName expected) - { - var field = value.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic) - .Single(f => f.FieldType == typeof(SqlTableName)); - var actual = (SqlTableName)field.GetValue(value)!; - Equal(expected.LocalName, actual.LocalName); - Equal(true, ReferenceEquals(expected.NamespaceSegments, actual.NamespaceSegments)); - } - - private static void Check(DbConnection conn) - { - Equal("user", conn.Db.User.RemoteTableName); - Equal("MyAuth.user", conn.Db.MyAuth.User.RemoteTableName); - Equal("class.user", conn.Db.@class.User.RemoteTableName); - Equal(conn.Db.MyAuth.User, conn.Db.GetTable("MyAuth.user")!); - Equal(conn.Db.@class.User, conn.Db.GetTable("class.user")!); - - var query = new QueryBuilder(); - Equal("SELECT * FROM \"user\"", query.From.User().ToSql()); - Equal("SELECT * FROM \"MyAuth\".\"user\"", query.From.MyAuth.User().ToSql()); - Equal("SELECT * FROM \"class\".\"user\"", query.From.@class.User().ToSql()); - var filtered = query.From.MyAuth.User().Where(cols => cols.Value.Eq(7U)).ToSql(); - if (!filtered.Contains("\"MyAuth\".\"user\".\"value\"")) throw new Exception(filtered); - var join = " FROM \"MyAuth\".\"user\" JOIN \"class\".\"user\" ON \"MyAuth\".\"user\".\"id\" = \"class\".\"user\".\"id\""; - Equal("SELECT \"MyAuth\".\"user\".*" + join, query.From.MyAuth.User().LeftSemijoin(query.From.@class.User(), (l, r) => l.Id.Eq(r.Id)).ToSql()); - Equal("SELECT \"class\".\"user\".*" + join, query.From.MyAuth.User().RightSemijoin(query.From.@class.User(), (l, r) => l.Id.Eq(r.Id)).ToSql()); - var all = QueryBuilder.AllTablesSqlQueries(); - Equal(9, all.Length); - Equal(all.Length, all.Distinct().Count()); - Equal(false, all.Any(sql => sql.Contains("secret"))); - var sqlName = typeof(Auth.RemoteTables.UserHandle).GetProperty("RemoteSqlTableName", BindingFlags.Instance | BindingFlags.NonPublic)!; - Equal("\"MyAuth\".\"user\"", sqlName.GetValue(conn.Db.MyAuth.User)!.ToString()); - var cachedName = Auth.RemoteTables.UserHandle.SqlName; - for (var i = 0; i < 2; i++) - Equal(true, ReferenceEquals(cachedName.NamespaceSegments, - ((SqlTableName)sqlName.GetValue(conn.Db.MyAuth.User)!).NamespaceSegments)); - var firstQuery = query.From.MyAuth.User(); - var secondQuery = query.From.MyAuth.User(); - Equal(false, ReferenceEquals(firstQuery, secondQuery)); - foreach (var tableQuery in new[] { firstQuery, secondQuery }) - { - CheckCachedSqlName(tableQuery, cachedName); - foreach (var property in new[] { "Cols", "IxCols" }) - { - var columns = tableQuery.GetType().GetProperty(property, - BindingFlags.Instance | BindingFlags.NonPublic)!.GetValue(tableQuery)!; - foreach (var column in columns.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public)) - CheckCachedSqlName(column.GetValue(columns)!, cachedName); - } - } - Equal(false, ReferenceEquals(cachedName.NamespaceSegments, - Audit.RemoteTables.UserHandle.SqlName.NamespaceSegments)); - - var root = new User(1, true); - var auth = new Auth.User(1, 7); - var audit = new Audit.User(1, "audit"); - int inserts = 0; - conn.Db.MyAuth.User.OnInsert += (ctx, row) => - { - Equal(conn.Db, ctx.Db); - Equal(1, ctx.Db.User.Count); - Equal(1, ctx.Db.@class.User.Count); - Equal(7U, row.Value); - inserts++; - }; - Apply(conn, - Change("user", new[] { root }, Array.Empty()), - Change("MyAuth.user", new[] { auth }, Array.Empty()), - Change("class.user", new[] { audit }, Array.Empty())); - Equal(1, inserts); - Equal(auth, conn.Db.MyAuth.User.Id.Find(1)); - Equal(audit, conn.Db.@class.User.Id.Find(1)); - Equal("audit", conn.Db.@class.User.Iter().Single().Value); - int updates = 0; - conn.Db.MyAuth.User.OnUpdate += (ctx, oldRow, newRow) => - { - Equal(7U, oldRow.Value); - Equal(8U, newRow.Value); - Equal("audit", ctx.Db.@class.User.Id.Find(1)!.Value); - updates++; - }; - var updatedAuth = new Auth.User(1, 8); - Apply(conn, Change("MyAuth.user", new[] { updatedAuth }, new[] { auth })); - Equal(1, updates); - auth = updatedAuth; - Apply(conn, Change("MyAuth.user", Array.Empty(), new[] { auth })); - Equal(0, conn.Db.MyAuth.User.Count); - Equal(1, conn.Db.User.Count); - Equal(1, conn.Db.@class.User.Count); - - int notices = 0; - conn.Db.MyAuth.Notice.OnInsert += (ctx, row) => { Equal(4UL, row.Id); notices++; }; - Apply(conn, new TableUpdate("MyAuth.notice", new List - { - new TableUpdateRows.EventTable(new EventTableRows(Rows(new Auth.Notice(4)))) - })); - Equal(1, notices); - - Equal("MyAuth.login", ((IReducerArgs)new Auth.Reducer.Login(auth)).ReducerName); - Equal("class.login", ((IReducerArgs)new Audit.Reducer.Login(audit)).ReducerName); - Equal("MyAuth.get_user", ((IProcedureArgs)new Auth.Procedure.GetUserArgs()).ProcedureName); - // Function-only types are emitted and remain in their owning typespace. - _ = new Auth.Procedure.GetPayload { Value = new Auth.Payload("auth") }; - _ = new Audit.Procedure.GetUser { Value = audit }; - _ = new Auth.Procedure.GetUser { Value = auth }; - - int authCalls = 0, auditCalls = 0, errors = 0; - conn.Reducers.MyAuth.OnLogin += (ctx, row) => { Equal(auth, row); authCalls++; }; - void OnAuditLogin(ReducerEventContext ctx, Audit.User row) { Equal(audit, row); auditCalls++; } - conn.Reducers.@class.OnLogin += OnAuditLogin; - conn.OnUnhandledReducerError += (ctx, error) => { Equal("failed", error.Message); errors++; }; - var dispatch = typeof(DbConnection).GetMethod("Dispatch", BindingFlags.NonPublic | BindingFlags.Instance)!; - void Dispatch(Reducer args, Status status) - { - var ev = new ReducerEvent(new Timestamp(0), status, Identity.From(new byte[32]), null, null, args); - dispatch.Invoke(conn, new object[] { new ReducerEventContext(conn, ev), args }); - } - Dispatch(new Auth.Reducer.Login(auth), new Status.Committed(new Unit())); - Dispatch(new Audit.Reducer.Login(audit), new Status.Committed(new Unit())); - conn.Reducers.@class.OnLogin -= OnAuditLogin; - Dispatch(new Audit.Reducer.Login(audit), new Status.Failed("failed")); - Equal(1, authCalls); - Equal(1, auditCalls); - Equal(1, errors); - Console.WriteLine("Namespace client checks passed."); - } -} diff --git a/crates/testing/tests/environment.rs b/crates/testing/tests/environment.rs index 4a791ad5b10..eca89fc3892 100644 --- a/crates/testing/tests/environment.rs +++ b/crates/testing/tests/environment.rs @@ -61,42 +61,86 @@ async fn expect_view_update(handle: &mut ModuleHandle) { assert_eq!(message.num_rows(), Some(2)); } -async fn check_submodule_scope(handle: &mut ModuleHandle, values: &mut Values) { - values.insert("EMPTY".into(), "root-visible".into()); - let module = publish(handle, values).await; - assert!(module - .info - .module_def - .reducer_by_name("my_lib.env_read_reducer") - .is_some()); +struct SubmoduleScopeCases { + reducer: &'static str, + procedures: &'static [&'static str], + // Canonical lookup name and SQL table expression, respectively. + views: &'static [(&'static str, &'static str)], + root_http_routes: &'static [&'static str], + secret_marker: &'static str, +} + +const TYPESCRIPT_SCOPE: SubmoduleScopeCases = SubmoduleScopeCases { + reducer: "my_lib.env_read_reducer", + procedures: &["my_lib.env_read_procedure", "my_lib.env_read_in_tx"], + views: &[ + ("my_lib.env_read_view", "my_lib.env_read_view"), + ("my_lib.env_read_sql_view", "my_lib.env_read_sql_view"), + ("env_read_root_sql_view", "env_read_root_sql_view"), + ], + root_http_routes: &["/env-child"], + secret_marker: "root-visible", +}; + +const CSHARP_SCOPE: SubmoduleScopeCases = SubmoduleScopeCases { + reducer: "MyAuth.expect_environment", + procedures: &["MyAuth.read_environment", "MyAuth.read_environment_in_tx"], + // C# covers both view context types. The raw-SQL bypass cases above remain TS-only. + views: &[ + ("MyAuth.environment_value", "\"MyAuth\".environment_value"), + ( + "MyAuth.anonymous_environment_value", + "\"MyAuth\".anonymous_environment_value", + ), + ], + root_http_routes: &["/root-environment", "/auth-environment"], + secret_marker: "root-secret-", +}; + +async fn check_submodule_scope( + handle: &ModuleHandle, + cases: &SubmoduleScopeCases, + reducer_args: FunctionArgs, + expected_http: &str, +) { + let module = handle.client.module(); + assert!(module.info.module_def.reducer_by_name(cases.reducer).is_some()); let child = module - .call_reducer( - Identity::ZERO, - None, - None, - None, - None, - "my_lib.env_read_reducer", - FunctionArgs::Nullary, - ) + .call_reducer(Identity::ZERO, None, None, None, None, cases.reducer, reducer_args) .await; - assert!(child.is_err() || child.unwrap().outcome.into_result().is_err()); - for procedure in ["my_lib.env_read_procedure", "my_lib.env_read_in_tx"] { + let error = match child { + Err(error) => format!("{error:#}"), + Ok(result) => format!( + "{:?}", + result + .outcome + .into_result() + .expect_err("submodule reducer read the root environment") + ), + }; + assert!( + !error.contains(cases.secret_marker), + "reducer error exposed environment data" + ); + for &procedure in cases.procedures { assert!(module.info.module_def.procedure_by_name(procedure).is_some()); let result = module .call_procedure(Identity::ZERO, None, None, procedure, FunctionArgs::Nullary) .await; - assert!(result.result.is_err(), "submodule procedure read the root environment"); + let error = result + .result + .err() + .expect("submodule procedure read the root environment"); + assert!( + !format!("{error:#}").contains(cases.secret_marker), + "procedure error exposed environment data" + ); } - for view in [ - "my_lib.env_read_view", - "my_lib.env_read_sql_view", - "env_read_root_sql_view", - ] { + for &(view, sql_table) in cases.views { assert!(module.info.module_def.view_by_name_with_module(view).is_some()); let result = spacetimedb::sql::execute::run( module.relational_db().clone(), - format!("SELECT * FROM {view}"), + format!("SELECT * FROM {sql_table}"), AuthCtx::for_current(Identity::ZERO), Some(module.info.subscriptions.clone()), Some(module.clone()), @@ -110,17 +154,22 @@ async fn check_submodule_scope(handle: &mut ModuleHandle, values: &mut Values) { Err(error) => { let error = format!("{error:#}"); assert!(!error.contains("not found"), "view failed before dispatch: {error}"); - assert!(!error.contains("root-visible"), "view error exposed environment data"); + assert!( + !error.contains(cases.secret_marker), + "view error exposed environment data" + ); } } } // HTTP routes are root entries today. Calling an exported child callback // as an ordinary helper retains that root entry's authority. - assert_eq!( - &handle.call_http_route_get("/env-child").await.unwrap()[..], - b"root-visible" - ); + for route in cases.root_http_routes { + assert_eq!( + handle.call_http_route_get(route).await.unwrap().as_ref(), + expected_http.as_bytes() + ); + } } // Qualification can pin locally built inputs without invoking a nested build. @@ -292,7 +341,9 @@ fn exercise_fixture(name: &str) { } } if name == "module-test-ts" { - check_submodule_scope(&mut handle, &mut values).await; + values.insert("EMPTY".into(), "root-visible".into()); + publish(&handle, &values).await; + check_submodule_scope(&handle, &TYPESCRIPT_SCOPE, FunctionArgs::Nullary, "root-visible").await; } for key in ["UNDECLARED", "A=B"] { let result = handle @@ -343,6 +394,67 @@ fn csharp_environment_publish_and_checked_reads() { exercise_fixture("module-test-cs"); } +#[test] +#[serial] +fn namespace_csharp_environment_security() { + compiled_fixture("namespace-environment-test-cs").with_module_async_with_environment( + DEFAULT_CONFIG, + Values::from([ + ("NAMESPACE_TEST".into(), "root-secret-first".into()), + ("PUBLIC_LIBRARY_TEST".into(), "public-library-secret".into()), + ]), + |handle| async move { + for value in [Some("root-secret-first"), Some("root-secret-second"), Some(""), None] { + let mut values = Values::from([("PUBLIC_LIBRARY_TEST".into(), "public-library-secret".into())]); + if let Some(value) = value { + values.insert("NAMESPACE_TEST".into(), value.into()); + } + let module = publish(&handle, &values).await; + let expected = value.unwrap_or("unset"); + handle + .call_reducer_binary("expect_environment", &product![value]) + .await + .unwrap(); + check_submodule_scope( + &handle, + &CSHARP_SCOPE, + FunctionArgs::Bsatn(bsatn::to_vec(&product![value]).unwrap().into()), + expected, + ) + .await; + // Denied child calls must not leave subsequent root calls in the child scope. + // The root procedure also checks ordinary library helpers and transactions. + assert_eq!( + handle.call_procedure_with_args("read_environment", "[]").await.unwrap(), + AlgebraicValue::String(expected.into()) + ); + assert_eq!( + handle + .call_procedure_with_args("read_public_environment", "[]") + .await + .unwrap(), + AlgebraicValue::String("public-library-secret".into()) + ); + for view in ["environment_value", "anonymous_environment_value"] { + assert_eq!( + sql(&module, &format!("SELECT * FROM {view}")).await, + vec![product![expected]] + ); + } + let denied = handle + .call_procedure_with_args("read_environment_key", r#"["UNDECLARED"]"#) + .await + .expect_err("even root calls must not read undeclared keys"); + assert!(!format!("{denied:#}").contains(CSHARP_SCOPE.secret_marker)); + assert_eq!( + handle.call_procedure_with_args("read_environment", "[]").await.unwrap(), + AlgebraicValue::String(expected.into()) + ); + } + }, + ); +} + #[cfg(feature = "allow_loopback_http_for_tests")] #[test] #[serial] diff --git a/crates/testing/tests/standalone_integration_test.rs b/crates/testing/tests/standalone_integration_test.rs index 30965fe09c0..7b7d452d454 100644 --- a/crates/testing/tests/standalone_integration_test.rs +++ b/crates/testing/tests/standalone_integration_test.rs @@ -174,117 +174,6 @@ fn namespace_csharp_cross_namespace_calls() { ); } -#[test] -#[serial] -fn namespace_csharp_mounted_dependencies() { - init(); - CompiledModule::compile("namespace-test-cs", CompilationMode::Debug).with_module_async( - DEFAULT_CONFIG, - |mut module| async move { - // Library helpers inherit a root call's environment access; host-dispatched children do not. - assert_eq!( - module.call_procedure_with_args("read_environment", "[]").await.unwrap(), - AlgebraicValue::String("unset".into()) - ); - assert!(module - .call_procedure_with_args("MyAuth.read_environment", "[]") - .await - .is_err()); - // Extra is discovered without any application reference to its helpers. - module.call_reducer_binary("extra", &product![]).await.unwrap(); - module.call_reducer_binary("exercise", &product![]).await.unwrap(); - assert!(module.read_log(None).await.contains("namespace composition works")); - module - .call_reducer_binary("MyAuth.add", &product![10u32]) - .await - .unwrap(); - module.call_reducer_binary("class.add", &product![11u32]).await.unwrap(); - assert_eq!( - module.call_procedure_with_args("count_users", "[]").await.unwrap(), - AlgebraicValue::U64(5) - ); - for name in ["MyAuth.count_users", "class.count_users"] { - assert_eq!( - module.call_procedure_with_args(name, "[]").await.unwrap(), - AlgebraicValue::U64(2) - ); - } - assert_eq!(module.call_http_route_get("/auth-count").await.unwrap().as_ref(), b"2"); - - module - .client - .subscribe( - spacetimedb_client_api_messages::websocket::v1::Subscribe { - query_strings: [ - "SELECT * FROM users", - "SELECT * FROM auth_users", - "SELECT * FROM extra_rows", - "SELECT * FROM \"MyAuth\".users", - "SELECT * FROM \"MyAuth\".anonymous_users", - "SELECT * FROM query_users", - "SELECT * FROM query_users_right", - "SELECT * FROM query_extra", - "SELECT * FROM \"MyAuth\".query_users", - ] - .map(Box::::from) - .into(), - request_id: 99, - }, - Instant::now(), - ) - .await - .unwrap(); - tokio::time::timeout(Duration::from_secs(10), async { - while let Some(message) = module.recv_message().await { - if let spacetimedb::client::OutboundMessage::V1( - spacetimedb::client::messages::SerializableMessage::Subscribe(update), - ) = message - { - use spacetimedb_client_api_messages::websocket::v1::{ - DatabaseUpdate, FormatSwitch, WebsocketFormat, - }; - fn table_counts( - update: DatabaseUpdate, - ) -> std::collections::BTreeMap { - assert_eq!(update.tables.len(), 9, "one update per subscribed table/view"); - update - .tables - .into_iter() - .map(|table| (table.table_name.to_string(), table.num_rows)) - .collect() - } - assert_eq!(update.request_id, Some(99)); - let counts = match update.database_update { - FormatSwitch::Bsatn(update) => table_counts(update), - FormatSwitch::Json(update) => table_counts(update), - }; - assert_eq!( - counts, - [ - ("users", 1), - ("auth_users", 1), - ("extra_rows", 1), - ("MyAuth.users", 1), - ("MyAuth.anonymous_users", 1), - ("query_users", 1), - ("query_users_right", 1), - ("query_extra", 1), - ("MyAuth.query_users", 1), - ] - .map(|(name, count)| (name.to_owned(), count)) - .into() - ); - return; - } - } - panic!("connection closed before the view subscription response"); - }) - .await - .unwrap(); - }, - ); -} - #[test] #[serial] fn test_calling_a_reducer_typescript() { diff --git a/modules/namespace-environment-test-cs/Lib.cs b/modules/namespace-environment-test-cs/Lib.cs new file mode 100644 index 00000000000..9299fc78ca8 --- /dev/null +++ b/modules/namespace-environment-test-cs/Lib.cs @@ -0,0 +1,57 @@ +using SpacetimeDB; + +[assembly: Namespace(typeof(AuthLib.Functions), Accessor = "MyAuth")] + +namespace NamespaceRoot; + +[SpacetimeDB.Env] +public struct EnvironmentSchema +{ + public string? NAMESPACE_TEST; +} + +public static partial class Functions +{ + [Procedure] + public static string ReadEnvironment(ProcedureContext ctx) + { + var value = ctx.Env.NAMESPACE_TEST; + if (AuthLib.Functions.ReadEnvironment(ctx) != (value ?? "unset")) + throw new Exception("Library helper must retain root environment access"); + if (AuthLib.Functions.ReadEnvironmentInTx(ctx) != (value ?? "unset")) + throw new Exception("Library transaction helper must retain root environment access"); + return ctx.WithTx(tx => + { + if (tx.Env.NAMESPACE_TEST != value) + throw new Exception("Root transaction environment mismatch"); + return value ?? "unset"; + }); + } + + [HttpRouter] + public static Router Routes() => + Router.New().Get("/root-environment", new Handler(nameof(RootEnvironment))); + + [Reducer] + public static void ExpectEnvironment(ReducerContext ctx, string? expected) + { + if (ctx.Env.NAMESPACE_TEST != expected) + throw new Exception("Root environment mismatch"); + AuthLib.Functions.ExpectEnvironment(ctx, expected); + } + + [Procedure] + public static string? ReadEnvironmentKey(ProcedureContext ctx, string key) => ctx.Env.Get(key); + + [HttpHandler] + public static HttpResponse RootEnvironment(HandlerContext ctx, HttpRequest request) => + AuthLib.Functions.EnvironmentHandler(ctx, request); + + [View(Accessor = "EnvironmentValue", Public = true)] + public static AuthLib.EnvironmentValue? EnvironmentValue(ViewContext ctx) => + AuthLib.Functions.EnvironmentValue(ctx); + + [View(Accessor = "AnonymousEnvironmentValue", Public = true)] + public static AuthLib.EnvironmentValue? AnonymousEnvironmentValue(AnonymousViewContext ctx) => + AuthLib.Functions.AnonymousEnvironmentValue(ctx); +} diff --git a/modules/namespace-environment-test-cs/README.md b/modules/namespace-environment-test-cs/README.md new file mode 100644 index 00000000000..ec3997b827b --- /dev/null +++ b/modules/namespace-environment-test-cs/README.md @@ -0,0 +1,30 @@ +# Namespace Environment Security Fixture + +Run with `cargo test -p spacetimedb-testing --test environment namespace_csharp_environment_security`. +The test is also included by the `namespace_csharp` selector. The fixture requires .NET 10. + +The `environment` suite shares `check_submodule_scope` between this test and +`typescript_environment_publish_and_checked_reads`. The case lists record each +language's entrypoint names and coverage: TypeScript additionally tests raw-SQL +bypass attempts; C# tests both sender and anonymous view contexts. C#-specific +declaration composition, root controls, and value-update checks stay in this test. + +The root declares an optional environment key. AuthLib is registered in `MyAuth`; +PublicLib is discovered automatically and contributes an environment declaration +and procedure to `public`. + +The test publishes a real value, replaces it, sets it to empty, and removes it. It verifies: + +- Root reads and ordinary cross-assembly helpers retain root authority. +- Host-dispatched namespaced reducers, procedures (including transactions), and + sender/anonymous views cannot read the root environment. +- A rejected call does not prevent subsequent root reads, or expose the value in errors. +- Root callers still cannot read undeclared keys. +- A dependency registered in `public` can declare and read environment keys. +- HTTP routes remain root entries, including dependency-defined routes; handlers + and handler transactions retain root authority. + +Root views intentionally expose the test value as a positive control. Child views +intentionally fail, so this fixture is separate from the general namespace client +regression that subscribes to all public tables and views. As in the TypeScript +environment tests, failed views may return no rows instead of an error (issue #5912). diff --git a/modules/namespace-environment-test-cs/libraries/AuthLib/AuthLib.csproj b/modules/namespace-environment-test-cs/libraries/AuthLib/AuthLib.csproj new file mode 100644 index 00000000000..05c7687b3b1 --- /dev/null +++ b/modules/namespace-environment-test-cs/libraries/AuthLib/AuthLib.csproj @@ -0,0 +1,11 @@ + + + net10.0 + NamespaceEnvironmentAuthLib + $(AssemblyName) + + + + + + diff --git a/modules/namespace-environment-test-cs/libraries/AuthLib/Lib.cs b/modules/namespace-environment-test-cs/libraries/AuthLib/Lib.cs new file mode 100644 index 00000000000..69555d4994c --- /dev/null +++ b/modules/namespace-environment-test-cs/libraries/AuthLib/Lib.cs @@ -0,0 +1,50 @@ +using SpacetimeDB; + +#pragma warning disable STDB_UNSTABLE + +namespace AuthLib; + +[SpacetimeDB.Type] +public partial struct EnvironmentValue +{ + public string Value; +} + +public static partial class Functions +{ + [Procedure] + public static string ReadEnvironment(ProcedureContext ctx) => + ctx.Env.Get("NAMESPACE_TEST") ?? "unset"; + + [HttpRouter] + public static Router Routes() => + Router.New().Get("/auth-environment", new Handler(nameof(EnvironmentHandler))); + + [Reducer] + public static void ExpectEnvironment(ReducerContext ctx, string? expected) + { + if (ctx.Env.Get("NAMESPACE_TEST") != expected) + throw new Exception("Library environment mismatch"); + } + + [Procedure] + public static string ReadEnvironmentInTx(ProcedureContext ctx) => + ctx.WithTx(tx => tx.Env.Get("NAMESPACE_TEST") ?? "unset"); + + [HttpHandler] + public static HttpResponse EnvironmentHandler(HandlerContext ctx, HttpRequest request) + { + var value = ctx.Env.Get("NAMESPACE_TEST"); + if (ctx.WithTx(tx => tx.Env.Get("NAMESPACE_TEST")) != value) + throw new Exception("Handler transaction environment mismatch"); + return new(200, HttpVersion.Http11, [], HttpBody.FromString(value ?? "unset")); + } + + [View(Accessor = "EnvironmentValue", Public = true)] + public static EnvironmentValue? EnvironmentValue(ViewContext ctx) => + new EnvironmentValue { Value = ctx.Env.Get("NAMESPACE_TEST") ?? "unset" }; + + [View(Accessor = "AnonymousEnvironmentValue", Public = true)] + public static EnvironmentValue? AnonymousEnvironmentValue(AnonymousViewContext ctx) => + new EnvironmentValue { Value = ctx.Env.Get("NAMESPACE_TEST") ?? "unset" }; +} diff --git a/modules/namespace-environment-test-cs/libraries/PublicLib/Lib.cs b/modules/namespace-environment-test-cs/libraries/PublicLib/Lib.cs new file mode 100644 index 00000000000..40a7bfd1c2e --- /dev/null +++ b/modules/namespace-environment-test-cs/libraries/PublicLib/Lib.cs @@ -0,0 +1,21 @@ +using SpacetimeDB; + +namespace PublicLib; + +[SpacetimeDB.Env] +public struct EnvironmentSchema +{ + public string? PUBLIC_LIBRARY_TEST; +} + +public static partial class Functions +{ + [Procedure] + public static string ReadPublicEnvironment(ProcedureContext ctx) + { + var value = ctx.Env.PUBLIC_LIBRARY_TEST; + if (ctx.WithTx(tx => tx.Env.PUBLIC_LIBRARY_TEST) != value) + throw new Exception("Public library transaction environment mismatch"); + return value ?? "unset"; + } +} diff --git a/modules/namespace-environment-test-cs/libraries/PublicLib/PublicLib.csproj b/modules/namespace-environment-test-cs/libraries/PublicLib/PublicLib.csproj new file mode 100644 index 00000000000..4433be5c78d --- /dev/null +++ b/modules/namespace-environment-test-cs/libraries/PublicLib/PublicLib.csproj @@ -0,0 +1,11 @@ + + + net10.0 + NamespaceEnvironmentPublicLib + $(AssemblyName) + + + + + + diff --git a/modules/namespace-environment-test-cs/namespace-environment-test-cs.csproj b/modules/namespace-environment-test-cs/namespace-environment-test-cs.csproj new file mode 100644 index 00000000000..17958d46503 --- /dev/null +++ b/modules/namespace-environment-test-cs/namespace-environment-test-cs.csproj @@ -0,0 +1,12 @@ + + + net10.0 + + + + + + + + + diff --git a/modules/namespace-test-cs/Lib.cs b/modules/namespace-test-cs/Lib.cs index c2f33df74f8..a6736e71ca1 100644 --- a/modules/namespace-test-cs/Lib.cs +++ b/modules/namespace-test-cs/Lib.cs @@ -5,12 +5,6 @@ namespace NamespaceRoot; -[SpacetimeDB.Env] -public struct EnvironmentSchema -{ - public string? NAMESPACE_TEST; -} - [Table(Accessor = "User", Public = true)] public partial struct User { @@ -103,20 +97,6 @@ public static void Exercise(ReducerContext ctx) public static ulong CountUsers(ProcedureContext ctx) => ctx.WithTx(tx => tx.Db.User.Count + tx.Db.MyAuth.User.Count + tx.Db.@class.User.Count); - [Procedure] - public static string ReadEnvironment(ProcedureContext ctx) - { - var value = ctx.Env.NAMESPACE_TEST; - if (AuthLib.Functions.ReadEnvironment(ctx) != (value ?? "unset")) - throw new Exception("Library helper must read the root invocation's environment"); - return ctx.WithTx(tx => - { - if (tx.Env.NAMESPACE_TEST != value) - throw new Exception("Transaction environment differs from procedure environment"); - return value ?? "unset"; - }); - } - [Procedure] public static uint WriteAcrossNamespaces(ProcedureContext ctx, uint id, bool fail) => ctx.WithTx(tx => diff --git a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs index 3c880847e6f..f24682c8730 100644 --- a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs +++ b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs @@ -85,10 +85,6 @@ public static uint ReadScore(ProcedureContext ctx, uint id) => [Procedure] public static ulong CountUsers(ProcedureContext ctx) => ctx.WithTx(tx => tx.Db.User.Count); - [Procedure] - public static string ReadEnvironment(ProcedureContext ctx) => - ctx.Env.Get("NAMESPACE_TEST") ?? "unset"; - [View(Accessor = "Users", Public = true)] public static User? Users(ViewContext ctx) { diff --git a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs index dcc0fa8fb51..75d82fbf800 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs @@ -252,21 +252,7 @@ void EmptyCache() procedures++; } ); - conn.Procedures.ReadEnvironment( - (_, result) => - { - Require(result.IsSuccess && result.Value == "unset", "Root environment access"); - procedures++; - } - ); - conn.Procedures.MyAuth.ReadEnvironment( - (_, result) => - { - Require(!result.IsSuccess, "Namespaced calls must not read the root environment"); - procedures++; - } - ); - Wait(() => procedures == 7, "namespaced procedure callbacks"); + Wait(() => procedures == 5, "namespaced procedure callbacks"); var updated = false; conn.Db.MyAuth.User.OnUpdate += (ctx, before, after) => diff --git a/sdks/csharp/examples~/regression-tests/namespaces/README.md b/sdks/csharp/examples~/regression-tests/namespaces/README.md index 7bffbbaf1f3..d574bb62552 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/README.md +++ b/sdks/csharp/examples~/regression-tests/namespaces/README.md @@ -34,8 +34,6 @@ Coverage: atomic subscription callbacks, and persisted results through one-off queries. - Same-named reducers/procedures in different namespaces, procedure success/error callbacks, and child reducer failures forwarded to the root connection. -- Root environment reads through typed accessors, a library helper and a procedure - transaction; rejection of environment reads in host-dispatched namespace procedures. - Insert/update/delete callbacks, unique/B-tree indexes, and reducer rollback. - Event rows, private-table access rejection, procedural/anonymous/query views. - Root-defined RLS on a public namespaced table: two distinct non-owner clients, @@ -50,3 +48,6 @@ Coverage: Assertions throw in both Debug and Release. Every asynchronous phase has a timeout. The generated bindings are committed and regenerated through the normal CLI path. + +Environment access and namespace isolation are covered separately by +`namespace_csharp_environment_security` in `crates/testing/tests/environment.rs`. diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadEnvironment.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadEnvironment.g.cs deleted file mode 100644 index 6667f82ff60..00000000000 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadEnvironment.g.cs +++ /dev/null @@ -1,65 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#nullable enable - -using System; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types.@MyAuth -{ - public sealed partial class RemoteProcedures : RemoteBase - { - public void ReadEnvironment(ProcedureCallback callback) - { - // Convert the clean callback to the wrapper callback - InternalReadEnvironment((ctx, result) => - { - if (result.IsSuccess && result.Value != null) - { - callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); - } - else - { - callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); - } - }); - } - - private void InternalReadEnvironment(ProcedureCallback callback) - { - conn.InternalCallProcedure(new Procedure.ReadEnvironmentArgs(), callback); - } - - } - - public abstract partial class Procedure - { - [SpacetimeDB.Type] - [DataContract] - public sealed partial class ReadEnvironment - { - [DataMember(Name = "Value")] - public string Value; - - public ReadEnvironment(string Value) - { - this.Value = Value; - } - - public ReadEnvironment() - { - this.Value = ""; - } - } - [SpacetimeDB.Type] - [DataContract] - public sealed partial class ReadEnvironmentArgs : Procedure, IProcedureArgs - { - string IProcedureArgs.ProcedureName => "MyAuth.read_environment"; - } - - } -} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/ReadEnvironment.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/ReadEnvironment.g.cs deleted file mode 100644 index e7c19213dd4..00000000000 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/ReadEnvironment.g.cs +++ /dev/null @@ -1,65 +0,0 @@ -// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE -// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. - -#nullable enable - -using System; -using SpacetimeDB.ClientApi; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace SpacetimeDB.Types -{ - public sealed partial class RemoteProcedures : RemoteBase - { - public void ReadEnvironment(ProcedureCallback callback) - { - // Convert the clean callback to the wrapper callback - InternalReadEnvironment((ctx, result) => - { - if (result.IsSuccess && result.Value != null) - { - callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); - } - else - { - callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); - } - }); - } - - private void InternalReadEnvironment(ProcedureCallback callback) - { - conn.InternalCallProcedure(new Procedure.ReadEnvironmentArgs(), callback); - } - - } - - public abstract partial class Procedure - { - [SpacetimeDB.Type] - [DataContract] - public sealed partial class ReadEnvironment - { - [DataMember(Name = "Value")] - public string Value; - - public ReadEnvironment(string Value) - { - this.Value = Value; - } - - public ReadEnvironment() - { - this.Value = ""; - } - } - [SpacetimeDB.Type] - [DataContract] - public sealed partial class ReadEnvironmentArgs : Procedure, IProcedureArgs - { - string IProcedureArgs.ProcedureName => "read_environment"; - } - - } -} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs index ad397d36f08..5627e6ff00f 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.10.1 (commit 9604ff61789b002b5fc92b43b12887aa54a369a4). +// This was generated using spacetimedb cli version 2.10.1 (commit de85a85791d645f0194c35e2e94a17ef52c079d3). #nullable enable From 8600a63367bb26d8eed455a5a95d4739d3b90342 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Wed, 23 Sep 2026 12:05:56 -0500 Subject: [PATCH 31/49] Improve restrictions enforcement --- TESTING.md | 27 ++++++++- crates/bindings-csharp/Codegen.Tests/Tests.cs | 39 +++++++++++++ .../ExtraCompilationErrors.net10.verified.txt | 4 +- .../diag/snapshots/Module#FFI.verified.cs | 1 + .../snapshots/Module.net10#FFI.verified.cs | 1 + .../snapshots/Module#FFI.verified.cs | 1 + .../snapshots/Module.net10#FFI.verified.cs | 1 + .../server/snapshots/Module#FFI.verified.cs | 2 + .../snapshots/Module.net10#FFI.verified.cs | 2 + crates/bindings-csharp/Codegen/Diag.cs | 8 +++ crates/bindings-csharp/Codegen/Module.cs | 10 ++++ crates/bindings-csharp/README.md | 58 ++++++++++++++++++- crates/bindings-csharp/Runtime/Attrs.cs | 5 ++ sdks/csharp/DEVELOP.md | 14 +++++ 14 files changed, 169 insertions(+), 4 deletions(-) diff --git a/TESTING.md b/TESTING.md index ac090c4afab..b8707089c0f 100644 --- a/TESTING.md +++ b/TESTING.md @@ -97,6 +97,31 @@ of either the module libraries or client SDKs: 5. Repeat steps 2 through 4 for any other client projects which ought to cover the same behavior. 6. Run the new test with the relevant `cargo test` command for that SDK. +## C# namespace coverage + +The namespace tests are integration tests, plus focused generator diagnostics: + +- `dotnet test crates/bindings-csharp/Codegen.Tests -f net8.0` and + `-f net10.0`: existing Verify fixtures on both targets; .NET 10 additionally + checks mount restrictions, generated-name diagnostics, and dependency discovery. +- `cargo test -p spacetimedb-testing --test standalone_integration_test namespace_csharp`: + independent dependency publication, root export selection, and cross-namespace + helper/HTTP calls. +- `cargo test -p spacetimedb-testing --test environment namespace_csharp_environment_security`: + root/public environment access and denial of namespaced host calls. +- `cargo test -p spacetimedb-codegen --test codegen`: codegen snapshots and a + generated C# client for a TypeScript submodule. +- The [namespace client regression](sdks/csharp/examples~/regression-tests/namespaces/README.md) + runs against the real .NET 10 module and covers tables, queries, subscriptions, + callbacks, scheduling, transactions, and root-defined RLS. The existing + `sdks/csharp/tools~/run-regression-tests.sh 8 10` harness includes it in the + .NET 10 module pass while retaining .NET 8 regressions. + +Use the local package setup in [DEVELOP.md](sdks/csharp/DEVELOP.md), not stale +published NuGet packages, when exercising changed query/runtime code. +Library-defined RLS inside named namespaces and cross-language module composition +are unsupported, not integration cases awaiting a passing assertion. + ## Schema parity tests `crates/schema/tests/ensure_same_schema.rs` is a separate but important companion to the SDK tests. @@ -142,4 +167,4 @@ To add a new module library to the Standalone integration test suite: and so you are free to ignore them. 3. Modify `crates/testing/tests/standalone_integration_test.rs` to define new `#[test] #[serial]` test functions which use your new `module-test-XX` module to do the same operations as the existing tests. -4. Run the tests with `cargo test -p spacetimedb-testing --test standalone_integration_test`. \ No newline at end of file +4. Run the tests with `cargo test -p spacetimedb-testing --test standalone_integration_test`. diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index fb506d75dbf..284e85490ad 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -558,6 +558,45 @@ [new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions "[assembly: SpacetimeDB.Namespace(typeof(Marker), Accessor = \"public\")]", lifecycle)); } + + foreach (var (source, declaration) in new[] + { + (""" + #pragma warning disable STDB_UNSTABLE + public static class Rules { + [SpacetimeDB.ClientVisibilityFilter] + public static readonly SpacetimeDB.Filter Visible = + new SpacetimeDB.Filter.Sql("SELECT * FROM Entry"); + } + """, "row-level security filters"), + ("[SpacetimeDB.Env] public struct Settings { public string SECRET; }", "environment variables"), + }) + { + var dependency = Emit(Generate(Create("RestrictedDependency", + "[SpacetimeDB.Table] public partial struct Entry { public uint Id; }\n" + source))); + var result = CSharpGeneratorDriver.Create( + [new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions + ).RunGenerators(Create("RestrictedConsumer", + "[assembly: SpacetimeDB.Namespace(typeof(Entry), Accessor = \"Auth\")]", + dependency)).GetRunResult(); + Assert.Contains(result.Diagnostics, diagnostic => + diagnostic.Severity == DiagnosticSeverity.Error + && diagnostic.GetMessage().Contains("RestrictedDependency") + && diagnostic.GetMessage().Contains("'Auth'") + && diagnostic.GetMessage().Contains(declaration) + && diagnostic.GetMessage().Contains("root scope")); + Generate(Create("FlatConsumer", "", dependency)); + Generate(Create("PublicConsumer", + "[assembly: SpacetimeDB.Namespace(typeof(Entry), Accessor = \"public\")]", + dependency)); + } + + // Empty environment schemas contain no keys and are permitted by the host. + var emptyEnvironment = Emit(Generate(Create("EmptyEnvironment", + "[SpacetimeDB.Env] public struct Settings { }"))); + Generate(Create("EmptyEnvironmentConsumer", + "[assembly: SpacetimeDB.Namespace(typeof(Settings), Accessor = \"Auth\")]", + emptyEnvironment)); } #endif diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt index d528135ba94..e6f8b198379 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt @@ -396,7 +396,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(808)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1030)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(809)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1031)]', Severity: Error, Descriptor: { Id: CS0121, @@ -419,7 +419,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(808)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1030)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(809)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1031)]', Severity: Error, Descriptor: { Id: CS0121, diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs index aaa98bc2f1a..c6d3771076b 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs @@ -939,6 +939,7 @@ public static partial class AssemblyDescriptor { public const string LifecycleReducers = "Reducers.TestDuplicateReducerKind1 (Init), Reducers.TestDuplicateReducerKind2 (Init)"; + public const string RootOnlyDeclarations = "row-level security filters"; public const int ReducerCount = 8; public const int ProcedureCount = 0; public const int HttpHandlerCount = 0; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs index c8e1d745a5b..64285098369 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs @@ -941,6 +941,7 @@ public static partial class AssemblyDescriptor { public const string LifecycleReducers = "Reducers.TestDuplicateReducerKind1 (Init), Reducers.TestDuplicateReducerKind2 (Init)"; + public const string RootOnlyDeclarations = "row-level security filters"; public const int ReducerCount = 8; public const int ProcedureCount = 0; public const int HttpHandlerCount = 0; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs index 6a100c6cb68..04bd0a70399 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs @@ -321,6 +321,7 @@ namespace SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31 public static partial class AssemblyDescriptor { public const string LifecycleReducers = ""; + public const string RootOnlyDeclarations = ""; public const int ReducerCount = 1; public const int ProcedureCount = 1; public const int HttpHandlerCount = 0; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs index d52efae243a..9bacea1666c 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs @@ -322,6 +322,7 @@ namespace SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31 public static partial class AssemblyDescriptor { public const string LifecycleReducers = ""; + public const string RootOnlyDeclarations = ""; public const int ReducerCount = 1; public const int ProcedureCount = 1; public const int HttpHandlerCount = 0; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs index a010611b096..fcde5428f1a 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs @@ -772,6 +772,8 @@ namespace SpacetimeDB.Generated.server_D513E4815F57969C public static partial class AssemblyDescriptor { public const string LifecycleReducers = "Timers.Init (Init)"; + public const string RootOnlyDeclarations = + "row-level security filters, environment variables"; public const int ReducerCount = 6; public const int ProcedureCount = 0; public const int HttpHandlerCount = 0; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs index 8aa87cfefbe..5920fbf63d7 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs @@ -778,6 +778,8 @@ namespace SpacetimeDB.Generated.server_D513E4815F57969C public static partial class AssemblyDescriptor { public const string LifecycleReducers = "Timers.Init (Init)"; + public const string RootOnlyDeclarations = + "row-level security filters, environment variables"; public const int ReducerCount = 6; public const int ProcedureCount = 0; public const int HttpHandlerCount = 0; diff --git a/crates/bindings-csharp/Codegen/Diag.cs b/crates/bindings-csharp/Codegen/Diag.cs index 5b54173166f..0d4009ac78c 100644 --- a/crates/bindings-csharp/Codegen/Diag.cs +++ b/crates/bindings-csharp/Codegen/Diag.cs @@ -400,4 +400,12 @@ string type ctx => $"Generated C# name '{ctx.scope}.{ctx.name}' is used by both {ctx.first} and {ctx.second}. Choose distinct accessors or member names.", ctx => ctx.location ); + + public static readonly ErrorDescriptor<(string assembly, string name, string declarations)> MountedRootOnlyDeclarations = + new( + group, + "Mounted dependency declares root-only configuration", + ctx => $"Dependency '{ctx.assembly}' mounted in namespace '{ctx.name}' declares {ctx.declarations}. These declarations are only supported in the root scope. Move them to the root, or omit the namespace declaration so the dependency registers automatically in public. Root-defined RLS may target namespace-qualified tables.", + _ => Location.None + ); } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 7e47e5fca2a..3f38e0e7d81 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -2199,6 +2199,7 @@ record AssemblyDeclaration( string DescriptorTypeName, bool DeclaresMounts, string LifecycleReducers, + string RootOnlyDeclarations, EquatableArray Tables, EquatableArray ReadOnlyTables, EquatableArray Queries @@ -2298,6 +2299,8 @@ marker is null attribute.AttributeClass?.ToDisplayString() == "SpacetimeDB.NamespaceAttribute"), descriptor.GetMembers("LifecycleReducers").OfType() .FirstOrDefault()?.ConstantValue as string ?? "", + descriptor.GetMembers("RootOnlyDeclarations").OfType() + .FirstOrDefault()?.ConstantValue as string ?? "", ReadAccessors("Tables"), ReadAccessors("ReadOnlyTables"), new(descriptor.GetTypeMembers("Queries").SelectMany(type => type.GetMembers()) @@ -2775,6 +2778,9 @@ bool IsChild(AssemblyDeclaration assembly) => foreach (var assembly in mountedAssemblies.Where(a => a.LifecycleReducers.Length != 0)) context.ReportDiagnostic(ErrorDescriptor.MountedLifecycleReducers.ToDiag( (assembly.Identity, mountByIdentity[assembly.Identity].Accessor, assembly.LifecycleReducers))); + foreach (var assembly in mountedAssemblies.Where(a => a.RootOnlyDeclarations.Length != 0)) + context.ReportDiagnostic(ErrorDescriptor.MountedRootOnlyDeclarations.ToDiag( + (assembly.Identity, mountByIdentity[assembly.Identity].Accessor, assembly.RootOnlyDeclarations))); string GenerateDispatchRouting(string category, string arguments, string unknownId) { @@ -3250,6 +3256,10 @@ internal AnonymousViewContext(Internal.LocalReadOnly db) namespace {{extensionNamespaceName}} { public static partial class AssemblyDescriptor { public const string LifecycleReducers = {{SymbolDisplay.FormatLiteral(string.Join(", ", addReducers.Where(r => r.Kind != ReducerKind.UserDefined).Select(r => $"{r.FullName} ({r.Kind})")), true)}}; + public const string RootOnlyDeclarations = {{SymbolDisplay.FormatLiteral(string.Join(", ", new[] { + rlsFilters.Array.Length != 0 ? "row-level security filters" : null, + environmentRegistrations.Length != 0 ? "environment variables" : null + }.Where(value => value is not null)), true)}}; public const int ReducerCount = {{addReducers.Array.Length}}; public const int ProcedureCount = {{addProcedures.Array.Length}}; public const int HttpHandlerCount = {{addHttpHandlers.Array.Length}}; diff --git a/crates/bindings-csharp/README.md b/crates/bindings-csharp/README.md index 764683928b7..048091d2c52 100644 --- a/crates/bindings-csharp/README.md +++ b/crates/bindings-csharp/README.md @@ -21,6 +21,62 @@ The [`Codegen`](./Codegen/) and [`Runtime`](./Runtime/) libraries are used: They provide all of the functionality needed to write SpacetimeDB modules in C#. See their READMEs for more information. +### Assembly dependencies and namespaces + +Assembly composition requires .NET 10 and C# 14 in both the root and its module +dependencies. Existing standalone .NET 8 modules keep their generated contexts; +they cannot participate in this assembly composition path. + +Reference another C# module with a normal `ProjectReference` (or a package +containing its compiled module assembly). No root/library build-role property is +required: the same dependency can also be published independently. +Descriptor-bearing dependencies, including transitive dependencies, register +automatically once in `public` unless the root assigns a namespace: + +```csharp +[assembly: SpacetimeDB.Namespace(typeof(AuthLib.Marker), Accessor = "MyAuth")] +``` + +The marker can be any accessible type declared in the dependency assembly. +The tested example is [namespace-test-cs](../../modules/namespace-test-cs/), +whose root references AuthLib, AuditLib, and ExtraLib. If libraries live beneath +the root project directory, exclude their source files from its compile glob, +as that example does. + +Root code uses `ctx.Db.MyAuth.User` and `ctx.From.MyAuth.User()`. Compiled +AuthLib helpers continue to use `ctx.Db.User` and `ctx.From.User()`, regardless +of the namespace selected by the root. Ordinary helper calls share the caller's +context and transaction; a namespace is not a security boundary between helpers. + +#### Current restrictions + +- Only the consuming root chooses namespace placement. A dependency that itself + declares namespace mounts cannot be composed, even in `public`. Nested mounts, + multiple instances of one assembly, and runtime-created namespaces are unsupported. +- An assembly can be mounted only once, and the root cannot mount itself. + Omitting the attribute, or explicitly using `Accessor = "public"`, registers + the dependency in the default scope with flat accessors. +- `Accessor` is currently both the C# accessor and database namespace. There is + no separate SQL-level `Name`. It must be a valid C# and database identifier, + at most 63 UTF-8 bytes. Names are checked for case-insensitive duplicates; + `st`, `spacetimedb`, and names starting with `pg_` are reserved. + Keywords use their plain spelling in the attribute and `@` in C# expressions. +- Named namespaces cannot declare lifecycle reducers, nonempty environment + schemas, or RLS filters. The generator rejects these when composing the root. + They remain valid when the dependency is published alone or registered in + `public`, subject to ordinary host validation (including lifecycle uniqueness). +- Define RLS in the root, using qualified table names, as in + [the integration fixture](../../modules/namespace-test-cs/Lib.cs). + Library-defined RLS in a named namespace is unsupported; it must not be relied + on to protect data. +- HTTP routes retain the existing root-level routing and environment authority; + mounting a dependency does not add an HTTP namespace prefix. +- Composition uses C# assemblies, not TypeScript or Rust module binaries. + Cross-language module composition is not implemented by this mechanism. + +These restrictions do not require C# 14 in clients. See +[C# namespace bindings](../../sdks/csharp/DEVELOP.md#namespace-bindings). + ### Declared environment A module may declare one `[SpacetimeDB.Env]` struct. `string` is required and @@ -50,7 +106,7 @@ them through its own outputs. Environment declarations register through each assembly's descriptor on .NET 10. Dependencies automatically registered in `public` contribute to the root schema; -mounted dependencies cannot declare environment variables (the host rejects them). +mounted dependencies cannot declare environment variables (the generator and host reject them). A library helper invoked by root code can use `ctx.Env.Get("KEY")` for a root-declared key. Calling that library through a namespaced host entrypoint does not grant environment access, even for a key declared by the root. diff --git a/crates/bindings-csharp/Runtime/Attrs.cs b/crates/bindings-csharp/Runtime/Attrs.cs index aaa83f23113..af1edcb5bc3 100644 --- a/crates/bindings-csharp/Runtime/Attrs.cs +++ b/crates/bindings-csharp/Runtime/Attrs.cs @@ -6,6 +6,11 @@ namespace SpacetimeDB /// The consuming module chooses the placement; the marker may be any accessible type. /// Requires .NET 10 and C# 14. /// + /// + /// An assembly may be mounted only once. Dependencies cannot declare mounts. + /// Named namespaces cannot contain lifecycle reducers, RLS filters, or nonempty + /// environment declarations. Dependencies without a mount register automatically in public. + /// [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public sealed class NamespaceAttribute(System.Type marker) : Attribute { diff --git a/sdks/csharp/DEVELOP.md b/sdks/csharp/DEVELOP.md index ba1f78c529d..18ec2b04d35 100644 --- a/sdks/csharp/DEVELOP.md +++ b/sdks/csharp/DEVELOP.md @@ -63,6 +63,20 @@ while a `User` row in the `MyAuth` database namespace becomes `Game.Bindings.MyAuth.User`. Their table handles remain `conn.Db.User` and `conn.Db.MyAuth.User`, respectively. +Generated bindings and the SDK retain the C# 9 / .NET Standard 2.1 baseline; +the module's C# 14 extension properties are not used in clients. Namespace +containers share one connection and table cache. + +Typed queries such as `q.From.MyAuth.User()` quote namespace and table segments +separately. Raw SQL must use the same database namespace, for example +`SELECT * FROM "MyAuth"."user"` for a table whose SQL name is `user`. +There is no separate namespace alias or SQL-level namespace name. + +The C# client also supports schemas produced by TypeScript submodules. This does +not mean a C# module can reference a TypeScript module as an assembly dependency, +nor establish namespace support in other client SDKs. Module-side restrictions +are documented in the [C# bindings README](../../crates/bindings-csharp/README.md#current-restrictions). + ### Runtime Structure Most of the core logic of the SDK lives in [`DbConnectionBase<...>`](./src/SpacetimeDBClient.cs). This handles: From bb4d909e3b24dde5d1273c8feaa1bfdd404e40bc Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 09:13:09 -0500 Subject: [PATCH 32/49] Remove .user file added by accident --- crates/bindings-csharp/SpacetimeSharpSATS.sln.DotSettings.user | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 crates/bindings-csharp/SpacetimeSharpSATS.sln.DotSettings.user diff --git a/crates/bindings-csharp/SpacetimeSharpSATS.sln.DotSettings.user b/crates/bindings-csharp/SpacetimeSharpSATS.sln.DotSettings.user deleted file mode 100644 index a29253dede0..00000000000 --- a/crates/bindings-csharp/SpacetimeSharpSATS.sln.DotSettings.user +++ /dev/null @@ -1,2 +0,0 @@ - - ForceIncluded \ No newline at end of file From cc320280c2881f2ba2cb451a96bc418077f8f48f Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 09:23:38 -0500 Subject: [PATCH 33/49] Remove extra test --- .../BSATN.Runtime.Tests/Tests.cs | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs b/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs index 8666ad3d5a2..703ff5a5b83 100644 --- a/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs +++ b/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs @@ -386,30 +386,6 @@ public static void GeneratedProductRoundTrip() ); } - [Fact] - public static void StructuralReadProductRoundTrip() - { - GenBasic.Sample( - value => - { - var row = new BasicDataClass(value); - using var stream = new MemoryStream(IStructuralReadWrite.ToBytes(row)); - using var reader = new BinaryReader(stream); - Assert.Equal(row, IStructuralReadWrite.Read(reader)); - Assert.Equal(stream.Length, stream.Position); - - stream.Position = 0; - Assert.Equal(new BasicDataStruct(value), IStructuralReadWrite.Read(reader)); - Assert.Equal(stream.Length, stream.Position); - - stream.Position = 0; - Assert.Equal(new BasicDataRecord(value), IStructuralReadWrite.Read(reader)); - Assert.Equal(stream.Length, stream.Position); - }, - iter: 10_000 - ); - } - [Fact] public static void GeneratedProductEqualsWorks() { From ef8984c752c17c6fcf6802683bb5253463aaa316 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 09:36:48 -0500 Subject: [PATCH 34/49] Simplify `SqlTableName` in `QueryBuilder` --- .../BSATN.Runtime/QueryBuilder.cs | 36 ++++++++----------- .../Runtime/Internal/NamespaceRegistry.cs | 2 +- crates/codegen/src/csharp.rs | 19 +++++----- .../MyAuth/Tables/AnonymousUsers.g.cs | 2 +- .../module_bindings/MyAuth/Tables/Notice.g.cs | 2 +- .../MyAuth/Tables/ProtectedRow.g.cs | 2 +- .../MyAuth/Tables/QueryUsers.g.cs | 2 +- .../MyAuth/Tables/ScheduleResult.g.cs | 2 +- .../module_bindings/MyAuth/Tables/User.g.cs | 2 +- .../module_bindings/MyAuth/Tables/Users.g.cs | 2 +- .../module_bindings/SpacetimeDBClient.g.cs | 2 +- .../class/Tables/ScheduleResult.g.cs | 2 +- .../module_bindings/class/Tables/User.g.cs | 2 +- sdks/csharp/tests~/QueryBuilderTests.cs | 19 +++++----- 14 files changed, 41 insertions(+), 55 deletions(-) diff --git a/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs b/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs index 0c9c561ffae..c5c6c1c0861 100644 --- a/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs +++ b/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs @@ -2,43 +2,35 @@ namespace SpacetimeDB; using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Globalization; -/// A table identifier with separately quoted namespace segments and local name. +/// A table identifier with a separately quoted optional namespace and local name. public readonly struct SqlTableName { - private readonly ReadOnlyCollection? namespaceSegments; - public IReadOnlyList NamespaceSegments => - namespaceSegments ?? (IReadOnlyList)[]; + public string? Namespace { get; } public string LocalName { get; } public SqlTableName(string localName) { LocalName = localName; - namespaceSegments = null; + Namespace = null; } - public SqlTableName(string[] namespaceSegments, string localName) + public SqlTableName(string @namespace, string localName) { -#if NET8_OR_GREATER - ArgumentNullException.ThrowIfNull(namespaceSegments); -#else - if (namespaceSegments is null) - throw new ArgumentNullException(nameof(namespaceSegments)); -#endif - this.namespaceSegments = Array.AsReadOnly((string[])namespaceSegments.Clone()); + if (@namespace is null) + { + throw new ArgumentNullException(nameof(@namespace)); + } + + Namespace = @namespace; LocalName = localName; } - public override string ToString() - { - var sql = ""; - if (namespaceSegments is not null) - foreach (var segment in namespaceSegments) - sql += SqlFormat.QuoteIdent(segment) + "."; - return sql + SqlFormat.QuoteIdent(LocalName); - } + public override string ToString() => + Namespace is null + ? SqlFormat.QuoteIdent(LocalName) + : SqlFormat.QuoteIdent(Namespace) + "." + SqlFormat.QuoteIdent(LocalName); } public readonly struct SqlLiteral diff --git a/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs b/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs index a93b3006e70..4244b9bc0fa 100644 --- a/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs +++ b/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs @@ -30,6 +30,6 @@ public string Resolve(string assemblyIdentity, string localName) => public SqlTableName ResolveSqlName(string assemblyIdentity, string localName) => ResolveNamespace(assemblyIdentity) is { } name - ? new SqlTableName([name], localName) + ? new SqlTableName(name, localName) : new SqlTableName(localName); } diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs index 30d475abf28..054e0b43a95 100644 --- a/crates/codegen/src/csharp.rs +++ b/crates/codegen/src/csharp.rs @@ -622,17 +622,14 @@ impl CsharpScope<'_> { } fn sql_name(&self, name: &Identifier) -> String { - let segments = self - .path - .segments() - .iter() - .map(|s| format!("{s:?}")) - .collect::>() - .join(", "); - format!( - "new global::SpacetimeDB.SqlTableName(new string[] {{ {segments} }}, {:?})", - name.deref() - ) + match self.path.segments() { + [] => format!("new global::SpacetimeDB.SqlTableName({:?})", name.deref()), + [namespace] => format!( + "new global::SpacetimeDB.SqlTableName({namespace:?}, {:?})", + name.deref() + ), + _ => panic!("Nested namespaces are not supported by C# bindings"), + } } fn child_members(&self, output: &mut CodeIndenter, module: &ModuleDef, container: &str) { diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs index 755f3a55dc7..89e143f18bf 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs @@ -16,7 +16,7 @@ public sealed partial class RemoteTables public sealed class AnonymousUsersHandle : RemoteTableHandle { public override string RemoteTableName => "MyAuth.anonymous_users"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "anonymous_users"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "anonymous_users"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; internal AnonymousUsersHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs index affc88589a2..450b3c5b841 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs @@ -16,7 +16,7 @@ public sealed partial class RemoteTables public sealed class NoticeHandle : RemoteEventTableHandle { public override string RemoteTableName => "MyAuth.notice"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "notice"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "notice"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; internal NoticeHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs index a9c089caf9e..afd6b5330e9 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs @@ -16,7 +16,7 @@ public sealed partial class RemoteTables public sealed class ProtectedRowHandle : RemoteTableHandle { public override string RemoteTableName => "MyAuth.protected_row"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "protected_row"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "protected_row"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class IdUniqueIndex : UniqueIndexBase diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs index 73eadac07fc..6c9d5029d5a 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs @@ -16,7 +16,7 @@ public sealed partial class RemoteTables public sealed class QueryUsersHandle : RemoteTableHandle { public override string RemoteTableName => "MyAuth.query_users"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "query_users"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "query_users"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class IdUniqueIndex : UniqueIndexBase diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs index dfb1a9ad6b2..a3b1e3ead3b 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs @@ -16,7 +16,7 @@ public sealed partial class RemoteTables public sealed class ScheduleResultHandle : RemoteTableHandle { public override string RemoteTableName => "MyAuth.schedule_result"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "schedule_result"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "schedule_result"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class JobIdUniqueIndex : UniqueIndexBase diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs index 88fea38b560..e3a0f740b38 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs @@ -16,7 +16,7 @@ public sealed partial class RemoteTables public sealed class UserHandle : RemoteTableHandle { public override string RemoteTableName => "MyAuth.auth_users"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "auth_users"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "auth_users"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class IdUniqueIndex : UniqueIndexBase diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs index ee3adfce836..caa835ebd7a 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs @@ -16,7 +16,7 @@ public sealed partial class RemoteTables public sealed class UsersHandle : RemoteTableHandle { public override string RemoteTableName => "MyAuth.users"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "MyAuth" }, "users"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "users"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; internal UsersHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs index 5627e6ff00f..4b67c9da2ce 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.10.1 (commit de85a85791d645f0194c35e2e94a17ef52c079d3). +// This was generated using spacetimedb cli version 2.11.0 (commit 33fe65db55dc769009e00053334c83522468e265). #nullable enable diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/ScheduleResult.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/ScheduleResult.g.cs index 823bc45e4b2..e844cce31fc 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/ScheduleResult.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/ScheduleResult.g.cs @@ -16,7 +16,7 @@ public sealed partial class RemoteTables public sealed class ScheduleResultHandle : RemoteTableHandle { public override string RemoteTableName => "class.schedule_result"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "schedule_result"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("class", "schedule_result"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class JobIdUniqueIndex : UniqueIndexBase diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/User.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/User.g.cs index 6d68770f97f..b9e8f835939 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/User.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/class/Tables/User.g.cs @@ -16,7 +16,7 @@ public sealed partial class RemoteTables public sealed class UserHandle : RemoteTableHandle { public override string RemoteTableName => "class.user"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName(new string[] { "class" }, "user"); + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("class", "user"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class IdUniqueIndex : UniqueIndexBase diff --git a/sdks/csharp/tests~/QueryBuilderTests.cs b/sdks/csharp/tests~/QueryBuilderTests.cs index 51913492b76..e8df8c5f745 100644 --- a/sdks/csharp/tests~/QueryBuilderTests.cs +++ b/sdks/csharp/tests~/QueryBuilderTests.cs @@ -95,16 +95,13 @@ private static Table MakeRightTable(string tab [Fact] - public void QualifiedName_QuotesSegmentsAndCopiesInput() + public void QualifiedName_QuotesNamespaceAndLocalName() { - var segments = new[] { "select", "we\"ird.namespace" }; - var name = new SqlTableName(segments, "users.with.dots"); - segments[0] = "changed"; - Assert.Equal(new[] { "select", "we\"ird.namespace" }, name.NamespaceSegments); + var name = new SqlTableName("we\"ird.namespace", "users.with.dots"); + Assert.Equal("we\"ird.namespace", name.Namespace); Assert.Equal("users.with.dots", name.LocalName); - Assert.Equal("\"select\".\"we\"\"ird.namespace\".\"users.with.dots\"", name.ToString()); - Assert.Throws(() => - ((System.Collections.Generic.IList)name.NamespaceSegments)[0] = "changed"); + Assert.Equal("\"we\"\"ird.namespace\".\"users.with.dots\"", name.ToString()); + Assert.Null(new SqlTableName("users").Namespace); Assert.Equal("SELECT * FROM \"auth.users\"", MakeTable("auth.users").ToSql()); Assert.Equal("\"auth.users\".\"id\"", new Col("auth.users", "id").ToString()); Assert.Equal("\"auth.users\".\"id\"", new IxCol("auth.users", "id").ToString()); @@ -113,8 +110,8 @@ public void QualifiedName_QuotesSegmentsAndCopiesInput() [Fact] public void QualifiedName_FiltersAndBothSemijoinsKeepSameLeafNamesDistinct() { - var leftName = new SqlTableName(new[] { "auth" }, "users"); - var rightName = new SqlTableName(new[] { "audit" }, "users"); + var leftName = new SqlTableName("auth", "users"); + var rightName = new SqlTableName("audit", "users"); var left = new Table, IxCol>( leftName, new(leftName, "id"), new(leftName, "id")); var right = new Table, IxCol>( @@ -128,7 +125,7 @@ public void QualifiedName_FiltersAndBothSemijoinsKeepSameLeafNamesDistinct() left.LeftSemijoin(right, (l, r) => l.Eq(r)).ToSql()); Assert.Equal("SELECT \"audit\".\"users\".*" + join, left.RightSemijoin(right, (l, r) => l.Eq(r)).ToSql()); - var escaped = new SqlTableName(new[] { "auth\"data" }, "select"); + var escaped = new SqlTableName("auth\"data", "select"); Assert.Equal("\"auth\"\"data\".\"select\".\"i\"\"d\"", new Col(escaped, "i\"d").ToString()); Assert.Equal("\"auth\"\"data\".\"select\".\"i\"\"d\"", new IxCol(escaped, "i\"d").ToString()); } From 2eed5ce5f0f660af0358546a6b6f5c0da258c393 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 09:59:40 -0500 Subject: [PATCH 35/49] Restore EnvironmentTests --- .../Codegen.Tests/EnvironmentTests.cs | 58 +------------------ 1 file changed, 2 insertions(+), 56 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs b/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs index 0af40264494..d3564f218ae 100644 --- a/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs +++ b/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs @@ -47,17 +47,13 @@ public static class Module { """; private static (Compilation Compilation, GeneratorDriverRunResult Result) Generate( - string declaration, - bool sharedContexts = false + string declaration ) { var references = ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES")!) .Split(Path.PathSeparator) .Select(path => MetadataReference.CreateFromFile(path)); - var parse = new CSharpParseOptions( - LanguageVersion.Preview, - preprocessorSymbols: sharedContexts ? ["NET10_0_OR_GREATER"] : [] - ); + var parse = new CSharpParseOptions(LanguageVersion.Preview); var compilation = CSharpCompilation.Create( "EnvironmentFixture" + Guid.NewGuid().ToString("N"), [CSharpSyntaxTree.ParseText(Host + declaration, parse)], @@ -69,59 +65,9 @@ [new EnvironmentGenerator().AsSourceGenerator()], parseOptions: parse ); driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var output, out _); - if (sharedContexts) - { - var generatedNamespace = driver - .GetRunResult() - .GeneratedTrees.Single() - .GetRoot() - .DescendantNodes() - .OfType() - .Single() - .Name; - output = output.AddSyntaxTrees( - CSharpSyntaxTree.ParseText("global using " + generatedNamespace + ";", parse) - ); - } return (output, driver.GetRunResult()); } -#if NET10_0_OR_GREATER - [Fact] - public static void SharedReceiverAccessorsKeepCheckedLiveReads() - { - var (compilation, result) = Generate( - """ - [SpacetimeDB.Env] public struct Declarations { - public string REQUIRED; - public string OPTIONAL; - [SpacetimeDB.EnvValues("prod", "dev")] public string MODE; - public string @class; - } - public static class Usage { - public static void Check() { - if (SpacetimeDB.Internal.Module.Declarations.Count != 0) - throw new System.Exception("environment registered before descriptor call"); - var env = new SpacetimeDB.DatabaseEnvironment(); - if (env.REQUIRED == env.REQUIRED || env.MODE != "prod" || env.@class != "keyword") - throw new System.Exception("bad shared accessor"); - try { _ = env.OPTIONAL; throw new System.Exception("missing required value accepted"); } - catch (System.InvalidOperationException) {} - try { env.Get("UNKNOWN"); throw new System.Exception("unchecked read"); } - catch (System.InvalidOperationException) {} - } - } - """, - sharedContexts: true - ); - Assert.Empty(result.Diagnostics); - using var stream = new MemoryStream(); - var emitted = compilation.Emit(stream); - Assert.True(emitted.Success, string.Join("\n", emitted.Diagnostics)); - Assembly.Load(stream.ToArray()).GetType("Usage")!.GetMethod("Check")!.Invoke(null, null); - } -#endif - [Fact] public static void NamedAccessorsKeepCheckedReadsAndRegisterCanonicalConstraints() { From 7bc237f711335d3b30c7607efdec5c6f0ca30aa2 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 11:33:34 -0500 Subject: [PATCH 36/49] Simplify diagnostics --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 4 +++- .../ExtraCompilationErrors.net10.verified.txt | 4 ++-- .../fixtures/diag/snapshots/Module#FFI.verified.cs | 5 ++--- .../diag/snapshots/Module.net10#FFI.verified.cs | 5 ++--- .../explicitnames/snapshots/Module#FFI.verified.cs | 1 - .../snapshots/Module.net10#FFI.verified.cs | 1 - .../server/snapshots/Module#FFI.verified.cs | 3 +-- .../server/snapshots/Module.net10#FFI.verified.cs | 3 +-- crates/bindings-csharp/Codegen/Diag.cs | 14 +++----------- crates/bindings-csharp/Codegen/Module.cs | 12 ++++-------- 10 files changed, 18 insertions(+), 34 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 284e85490ad..ba8d0bbb606 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -550,7 +550,9 @@ [new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions "[assembly: SpacetimeDB.Namespace(typeof(Marker), Accessor = \"Auth\")]", lifecycle)).GetRunResult(); Assert.Contains(lifecycleResult.Diagnostics, diagnostic => - diagnostic.GetMessage().Contains("LifecycleFunctions.Handle (" + kind + ")") + diagnostic.Severity == DiagnosticSeverity.Error + && diagnostic.Descriptor.Title.ToString() == "Root-only declarations in mounted dependency" + && diagnostic.GetMessage().Contains("LifecycleFunctions.Handle (" + kind + ")") && diagnostic.GetMessage().Contains("Auth")); // The same dependency can still be published alone or merged into the root scope. Generate(Create("FlatLifecycleConsumer", "", lifecycle)); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt index e6f8b198379..d528135ba94 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt @@ -396,7 +396,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(809)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1031)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(808)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1030)]', Severity: Error, Descriptor: { Id: CS0121, @@ -419,7 +419,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(809)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1031)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(808)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1030)]', Severity: Error, Descriptor: { Id: CS0121, diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs index c6d3771076b..a86b0ad8703 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs @@ -937,9 +937,8 @@ namespace SpacetimeDB.Generated.diag_4F830E2879BB50E3 { public static partial class AssemblyDescriptor { - public const string LifecycleReducers = - "Reducers.TestDuplicateReducerKind1 (Init), Reducers.TestDuplicateReducerKind2 (Init)"; - public const string RootOnlyDeclarations = "row-level security filters"; + public const string RootOnlyDeclarations = + "row-level security filters, lifecycle reducer Reducers.TestDuplicateReducerKind1 (Init), lifecycle reducer Reducers.TestDuplicateReducerKind2 (Init)"; public const int ReducerCount = 8; public const int ProcedureCount = 0; public const int HttpHandlerCount = 0; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs index 64285098369..7ddb7d50f5d 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs @@ -939,9 +939,8 @@ namespace SpacetimeDB.Generated.diag_4F830E2879BB50E3 { public static partial class AssemblyDescriptor { - public const string LifecycleReducers = - "Reducers.TestDuplicateReducerKind1 (Init), Reducers.TestDuplicateReducerKind2 (Init)"; - public const string RootOnlyDeclarations = "row-level security filters"; + public const string RootOnlyDeclarations = + "row-level security filters, lifecycle reducer Reducers.TestDuplicateReducerKind1 (Init), lifecycle reducer Reducers.TestDuplicateReducerKind2 (Init)"; public const int ReducerCount = 8; public const int ProcedureCount = 0; public const int HttpHandlerCount = 0; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs index 04bd0a70399..aa01b3f4454 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs @@ -320,7 +320,6 @@ namespace SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31 { public static partial class AssemblyDescriptor { - public const string LifecycleReducers = ""; public const string RootOnlyDeclarations = ""; public const int ReducerCount = 1; public const int ProcedureCount = 1; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs index 9bacea1666c..a7409943015 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs @@ -321,7 +321,6 @@ namespace SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31 { public static partial class AssemblyDescriptor { - public const string LifecycleReducers = ""; public const string RootOnlyDeclarations = ""; public const int ReducerCount = 1; public const int ProcedureCount = 1; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs index fcde5428f1a..eb2231687db 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs @@ -771,9 +771,8 @@ namespace SpacetimeDB.Generated.server_D513E4815F57969C { public static partial class AssemblyDescriptor { - public const string LifecycleReducers = "Timers.Init (Init)"; public const string RootOnlyDeclarations = - "row-level security filters, environment variables"; + "row-level security filters, environment variables, lifecycle reducer Timers.Init (Init)"; public const int ReducerCount = 6; public const int ProcedureCount = 0; public const int HttpHandlerCount = 0; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs index 5920fbf63d7..5150e08e255 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs @@ -777,9 +777,8 @@ namespace SpacetimeDB.Generated.server_D513E4815F57969C { public static partial class AssemblyDescriptor { - public const string LifecycleReducers = "Timers.Init (Init)"; public const string RootOnlyDeclarations = - "row-level security filters, environment variables"; + "row-level security filters, environment variables, lifecycle reducer Timers.Init (Init)"; public const int ReducerCount = 6; public const int ProcedureCount = 0; public const int HttpHandlerCount = 0; diff --git a/crates/bindings-csharp/Codegen/Diag.cs b/crates/bindings-csharp/Codegen/Diag.cs index 0d4009ac78c..6a5d7423e95 100644 --- a/crates/bindings-csharp/Codegen/Diag.cs +++ b/crates/bindings-csharp/Codegen/Diag.cs @@ -385,11 +385,11 @@ string type _ => Location.None ); - public static readonly ErrorDescriptor<(string assembly, string name, string reducers)> MountedLifecycleReducers = + public static readonly ErrorDescriptor<(string assembly, string name, string declarations)> MountedRootOnlyDeclarations = new( group, - "Mounted dependency declares lifecycle reducers", - ctx => $"Dependency '{ctx.assembly}' mounted in namespace '{ctx.name}' declares lifecycle reducers: {ctx.reducers}. Lifecycle reducers are only supported in the root scope; remove them or omit the dependency's namespace declaration so it registers automatically in public.", + "Root-only declarations in mounted dependency", + ctx => $"Dependency '{ctx.assembly}' mounted in namespace '{ctx.name}' declares {ctx.declarations}. These declarations are only supported in the root scope. Move them to the root, or omit the namespace declaration so the dependency registers automatically in public. Root-defined RLS may target namespace-qualified tables.", _ => Location.None ); @@ -400,12 +400,4 @@ string type ctx => $"Generated C# name '{ctx.scope}.{ctx.name}' is used by both {ctx.first} and {ctx.second}. Choose distinct accessors or member names.", ctx => ctx.location ); - - public static readonly ErrorDescriptor<(string assembly, string name, string declarations)> MountedRootOnlyDeclarations = - new( - group, - "Mounted dependency declares root-only configuration", - ctx => $"Dependency '{ctx.assembly}' mounted in namespace '{ctx.name}' declares {ctx.declarations}. These declarations are only supported in the root scope. Move them to the root, or omit the namespace declaration so the dependency registers automatically in public. Root-defined RLS may target namespace-qualified tables.", - _ => Location.None - ); } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 3f38e0e7d81..a25fa0824aa 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -2198,7 +2198,6 @@ record AssemblyDeclaration( string Identity, string DescriptorTypeName, bool DeclaresMounts, - string LifecycleReducers, string RootOnlyDeclarations, EquatableArray Tables, EquatableArray ReadOnlyTables, @@ -2297,8 +2296,6 @@ marker is null descriptor.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat), assembly.GetAttributes().Any(attribute => attribute.AttributeClass?.ToDisplayString() == "SpacetimeDB.NamespaceAttribute"), - descriptor.GetMembers("LifecycleReducers").OfType() - .FirstOrDefault()?.ConstantValue as string ?? "", descriptor.GetMembers("RootOnlyDeclarations").OfType() .FirstOrDefault()?.ConstantValue as string ?? "", ReadAccessors("Tables"), @@ -2775,9 +2772,6 @@ bool IsChild(AssemblyDeclaration assembly) => var registrationOrder = publicScopeAssemblies.Concat(mountedAssemblies).ToArray(); foreach (var assembly in assemblies.Where(a => a.DeclaresMounts)) context.ReportDiagnostic(ErrorDescriptor.DependencyNamespaceMounts.ToDiag(assembly.Identity)); - foreach (var assembly in mountedAssemblies.Where(a => a.LifecycleReducers.Length != 0)) - context.ReportDiagnostic(ErrorDescriptor.MountedLifecycleReducers.ToDiag( - (assembly.Identity, mountByIdentity[assembly.Identity].Accessor, assembly.LifecycleReducers))); foreach (var assembly in mountedAssemblies.Where(a => a.RootOnlyDeclarations.Length != 0)) context.ReportDiagnostic(ErrorDescriptor.MountedRootOnlyDeclarations.ToDiag( (assembly.Identity, mountByIdentity[assembly.Identity].Accessor, assembly.RootOnlyDeclarations))); @@ -3255,11 +3249,13 @@ internal AnonymousViewContext(Internal.LocalReadOnly db) #if NET10_0_OR_GREATER namespace {{extensionNamespaceName}} { public static partial class AssemblyDescriptor { - public const string LifecycleReducers = {{SymbolDisplay.FormatLiteral(string.Join(", ", addReducers.Where(r => r.Kind != ReducerKind.UserDefined).Select(r => $"{r.FullName} ({r.Kind})")), true)}}; public const string RootOnlyDeclarations = {{SymbolDisplay.FormatLiteral(string.Join(", ", new[] { rlsFilters.Array.Length != 0 ? "row-level security filters" : null, environmentRegistrations.Length != 0 ? "environment variables" : null - }.Where(value => value is not null)), true)}}; + }.Where(value => value is not null).Concat( + addReducers.Where(r => r.Kind != ReducerKind.UserDefined) + .Select(r => $"lifecycle reducer {r.FullName} ({r.Kind})") + )), true)}}; public const int ReducerCount = {{addReducers.Array.Length}}; public const int ProcedureCount = {{addProcedures.Array.Length}}; public const int HttpHandlerCount = {{addHttpHandlers.Array.Length}}; From f1f7bd2f3166de633a85893432a641592c136904 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 12:34:50 -0500 Subject: [PATCH 37/49] Move EnvironmentGenerator.InvalidDeclaration to Diag.cs --- .../BSATN.Runtime/BSATN/Runtime.cs | 4 +- .../BSATN.Runtime/QueryBuilder.cs | 6 +- .../Codegen.Tests/EnvironmentTests.cs | 2 +- crates/bindings-csharp/Codegen.Tests/Tests.cs | 532 ++++++++++++------ .../Codegen.Tests/fixtures/server/Lib.cs | 1 + crates/bindings-csharp/Codegen/Diag.cs | 51 +- crates/bindings-csharp/Codegen/Environment.cs | 16 +- crates/bindings-csharp/Codegen/Module.cs | 508 ++++++++++++----- .../Codegen/NamespaceDeclaration.cs | 4 +- crates/bindings-csharp/Runtime/Attrs.cs | 2 +- .../Runtime/Internal/Module.cs | 48 +- .../bindings-csharp/Runtime/ModuleContexts.cs | 76 ++- 12 files changed, 843 insertions(+), 407 deletions(-) diff --git a/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs b/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs index e38d1337713..a6c573c4ed4 100644 --- a/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs +++ b/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs @@ -58,7 +58,9 @@ public interface IStructuralReadWrite /// #if NET10_0_OR_GREATER // Avoid an extra per-row call in NativeAOT scan iterators. - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] + [System.Runtime.CompilerServices.MethodImpl( + System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining + )] #endif static T Read(BinaryReader reader) where T : IStructuralReadWrite, new() diff --git a/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs b/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs index c5c6c1c0861..e7260e94379 100644 --- a/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs +++ b/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs @@ -149,8 +149,7 @@ public readonly struct Col(SqlTableName tableName, string columnNa public Col(string tableName, string columnName) : this(new SqlTableName(tableName), columnName) { } - internal string RefSql => - $"{tableName}.{SqlFormat.QuoteIdent(columnName)}"; + internal string RefSql => $"{tableName}.{SqlFormat.QuoteIdent(columnName)}"; public BoolExpr Eq(SqlLiteral value) => new($"({RefSql} = {value.Sql})"); @@ -185,8 +184,7 @@ public readonly struct IxCol(SqlTableName tableName, string column public IxCol(string tableName, string columnName) : this(new SqlTableName(tableName), columnName) { } - internal string RefSql => - $"{tableName}.{SqlFormat.QuoteIdent(columnName)}"; + internal string RefSql => $"{tableName}.{SqlFormat.QuoteIdent(columnName)}"; public BoolExpr Eq(SqlLiteral value) => new($"({RefSql} = {value.Sql})"); diff --git a/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs b/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs index d3564f218ae..25dcd1f66de 100644 --- a/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs +++ b/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs @@ -162,7 +162,7 @@ public static void InvalidDeclarationsAreCompileErrors(string field) Assert.Contains( result.Diagnostics, diagnostic => - diagnostic.Id == "STDBENV001" && diagnostic.Severity == DiagnosticSeverity.Error + diagnostic.Id == "STDB0044" && diagnostic.Severity == DiagnosticSeverity.Error ); } diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index ba8d0bbb606..cdcf7df36a0 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -52,12 +52,21 @@ public static async Task Compile(string name) public Task Verify(string fileName, object target) { - if ((fileName == nameof(Module) || fileName == nameof(EnvironmentGenerator) || fileName == "ExtraCompilationErrors") - && ModuleTargetFramework == "net10.0") + if ( + ( + fileName == nameof(Module) + || fileName == nameof(EnvironmentGenerator) + || fileName == "ExtraCompilationErrors" + ) + && ModuleTargetFramework == "net10.0" + ) { fileName += ".net10"; } - return Verifier.Verify(target).UseDirectory($"{projectDir}/snapshots").UseFileName(fileName); + return Verifier + .Verify(target) + .UseDirectory($"{projectDir}/snapshots") + .UseFileName(fileName); } private static CSharpGeneratorDriver CreateDriver( @@ -196,20 +205,23 @@ static void AssertContextOwnership(Compilation compilation) Assert.NotNull(runtimeAssembly); // Use the fixture's target, not the test host: the .NET 10 suite also compiles .NET 8 examples. - var sharedContexts = ((CSharpParseOptions)compilation.SyntaxTrees.First().Options) - .PreprocessorSymbolNames.Contains("NET10_0_OR_GREATER"); - foreach (var name in new[] - { - "SpacetimeDB.Local", - "SpacetimeDB.ReducerContext", - "SpacetimeDB.ProcedureContext", - "SpacetimeDB.ProcedureTxContext", - "SpacetimeDB.HandlerContext", - "SpacetimeDB.HandlerTxContext", - "SpacetimeDB.ViewContext", - "SpacetimeDB.AnonymousViewContext", - "SpacetimeDB.QueryBuilder", - }) + var sharedContexts = ( + (CSharpParseOptions)compilation.SyntaxTrees.First().Options + ).PreprocessorSymbolNames.Contains("NET10_0_OR_GREATER"); + foreach ( + var name in new[] + { + "SpacetimeDB.Local", + "SpacetimeDB.ReducerContext", + "SpacetimeDB.ProcedureContext", + "SpacetimeDB.ProcedureTxContext", + "SpacetimeDB.HandlerContext", + "SpacetimeDB.HandlerTxContext", + "SpacetimeDB.ViewContext", + "SpacetimeDB.AnonymousViewContext", + "SpacetimeDB.QueryBuilder", + } + ) { var runtimeType = runtimeAssembly!.GetTypeByMetadataName(name); var generatedType = compilation.Assembly.GetTypeByMetadataName(name); @@ -260,9 +272,14 @@ static void AssertNoCs0436Diagnostics(Compilation compilation) public static async Task NamespaceDeclarationsParseAndValidate() { var fixture = await Fixture.Compile("server"); - const string usings = "global using System; global using System.IO; " + const string usings = + "global using System; global using System.IO; " + "global using System.Collections.Generic; global using System.Linq;\n"; - CSharpCompilation Create(string name, string source, params MetadataReference[] references) => + CSharpCompilation Create( + string name, + string source, + params MetadataReference[] references + ) => CSharpCompilation.Create( name, [CSharpSyntaxTree.ParseText(usings + source, fixture.ParseOptions)], @@ -271,18 +288,29 @@ CSharpCompilation Create(string name, string source, params MetadataReference[] ); MetadataReference Dependency(string name) { - var compilation = Create(name, $$""" + var compilation = Create( + name, + $$""" namespace {{name}} { public class Marker { } [SpacetimeDB.Table(Accessor = "{{name}}Row")] public partial struct Row { public uint Id; } } - """); + """ + ); var driver = CSharpGeneratorDriver.Create( - [new Type().AsSourceGenerator(), new Module().AsSourceGenerator(), new EnvironmentGenerator().AsSourceGenerator()], + [ + new Type().AsSourceGenerator(), + new Module().AsSourceGenerator(), + new EnvironmentGenerator().AsSourceGenerator(), + ], parseOptions: fixture.ParseOptions ); - driver.RunGeneratorsAndUpdateCompilation(compilation, out var output, out var diagnostics); + driver.RunGeneratorsAndUpdateCompilation( + compilation, + out var output, + out var diagnostics + ); Assert.Empty(diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error)); using var dll = new MemoryStream(); var emitted = output.Emit(dll); @@ -293,14 +321,17 @@ public partial struct Row { public uint Id; } var audit = Dependency("Audit"); string Mount(string marker = "Auth.Marker", string accessor = "MyAuth") => $"[assembly: SpacetimeDB.Namespace(typeof({marker}), Accessor = \"{accessor}\")]\n"; - GeneratorDriver Run(string source) => CSharpGeneratorDriver.Create( - [new Module().AsSourceGenerator()], - parseOptions: fixture.ParseOptions, - driverOptions: new GeneratorDriverOptions( - IncrementalGeneratorOutputKind.None, - trackIncrementalGeneratorSteps: true + GeneratorDriver Run(string source) => + CSharpGeneratorDriver + .Create( + [new Module().AsSourceGenerator()], + parseOptions: fixture.ParseOptions, + driverOptions: new GeneratorDriverOptions( + IncrementalGeneratorOutputKind.None, + trackIncrementalGeneratorSteps: true + ) ) - ).RunGenerators(Create("Consumer", source, auth, audit)); + .RunGenerators(Create("Consumer", source, auth, audit)); void Reject(string source, string message) { var diagnostics = Run(source).GetRunResult().Diagnostics; @@ -308,9 +339,17 @@ void Reject(string source, string message) Assert.All(diagnostics, d => Assert.True(d.Location.IsInSource, d.ToString())); } - object[] Parsed(GeneratorDriver driver) => [.. driver.GetRunResult().Results.Single() - .TrackedSteps["SpacetimeDB.Namespace.Parse"].Single().Outputs - .SelectMany(o => ((System.Collections.IEnumerable)o.Value).Cast())]; + object[] Parsed(GeneratorDriver driver) => + [ + .. driver + .GetRunResult() + .Results.Single() + .TrackedSteps["SpacetimeDB.Namespace.Parse"] + .Single() + .Outputs.SelectMany(o => + ((System.Collections.IEnumerable)o.Value).Cast() + ), + ]; Assert.Empty(Run(Mount(accessor: new string('a', 63))).GetRunResult().Diagnostics); Assert.Empty(Run(Mount(accessor: "public")).GetRunResult().Diagnostics); Reject(Mount(accessor: new string('a', 64)), "63 UTF-8 bytes"); @@ -329,16 +368,24 @@ object[] Parsed(GeneratorDriver driver) => [.. driver.GetRunResult().Results.Sin Reject(Mount() + Mount(accessor: "Other"), "only be mounted once"); Reject(Mount() + Mount("Audit.Marker", "MYAUTH"), "case-insensitive"); Reject(Mount() + Mount("Audit.Marker", "MyAuth"), "accessor 'MyAuth'"); - Reject(Mount() + "[SpacetimeDB.Table(Accessor = \"MyAuth\")] public partial struct Row { public uint Id; }", - "root table accessor"); + Reject( + Mount() + + "[SpacetimeDB.Table(Accessor = \"MyAuth\")] public partial struct Row { public uint Id; }", + "root table accessor" + ); var oldLanguage = fixture.ParseOptions.WithLanguageVersion(LanguageVersion.CSharp13); - var oldCompilation = Create("Consumer", "", auth, audit).RemoveAllSyntaxTrees() + var oldCompilation = Create("Consumer", "", auth, audit) + .RemoveAllSyntaxTrees() .AddSyntaxTrees(CSharpSyntaxTree.ParseText(usings + Mount(), oldLanguage)); - var oldResult = CSharpGeneratorDriver.Create( - [new Module().AsSourceGenerator()], parseOptions: oldLanguage - ).RunGenerators(oldCompilation).GetRunResult(); - Assert.Contains(oldResult.Diagnostics, d => d.GetMessage().Contains("require .NET 10 and C# 14")); + var oldResult = CSharpGeneratorDriver + .Create([new Module().AsSourceGenerator()], parseOptions: oldLanguage) + .RunGenerators(oldCompilation) + .GetRunResult(); + Assert.Contains( + oldResult.Diagnostics, + d => d.GetMessage().Contains("require .NET 10 and C# 14") + ); var original = Run(Mount()); foreach (var source in new[] { Mount(accessor: "Other"), Mount(accessor: "class") }) @@ -347,12 +394,16 @@ [new Module().AsSourceGenerator()], parseOptions: oldLanguage Assert.Empty(changed.GetRunResult().Diagnostics); Assert.NotEqual(Assert.Single(Parsed(original)), Assert.Single(Parsed(changed))); Assert.Contains( - changed.GetRunResult().Results.Single().TrackedSteps["SpacetimeDB.Namespace.Parse"] + changed + .GetRunResult() + .Results.Single() + .TrackedSteps["SpacetimeDB.Namespace.Parse"] .SelectMany(s => s.Outputs), o => o.Reason == IncrementalStepRunReason.Modified ); } } + [Fact] public static async Task NamespaceGeneratedNameCollisions() { @@ -361,51 +412,93 @@ public static async Task NamespaceGeneratedNameCollisions() { var compilation = CSharpCompilation.Create( "CollisionProof", - [CSharpSyntaxTree.ParseText("global using System; global using System.IO; global using System.Collections.Generic;\n" + source, fixture.ParseOptions)], + [ + CSharpSyntaxTree.ParseText( + "global using System; global using System.IO; global using System.Collections.Generic;\n" + + source, + fixture.ParseOptions + ), + ], fixture.SampleCompilation.References, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) ); - CSharpGeneratorDriver.Create( - [new Type().AsSourceGenerator(), new Module().AsSourceGenerator(), new EnvironmentGenerator().AsSourceGenerator()], - parseOptions: fixture.ParseOptions - ).RunGeneratorsAndUpdateCompilation(compilation, out var output, out var diagnostics); + CSharpGeneratorDriver + .Create( + [ + new Type().AsSourceGenerator(), + new Module().AsSourceGenerator(), + new EnvironmentGenerator().AsSourceGenerator(), + ], + parseOptions: fixture.ParseOptions + ) + .RunGeneratorsAndUpdateCompilation( + compilation, + out var output, + out var diagnostics + ); return (output, diagnostics); } - foreach (var (accessor, fields, symbol) in new[] - { - ("User", "[SpacetimeDB.Unique] public uint Count;", "Count"), - ("User", "[SpacetimeDB.Unique] public uint Id; [SpacetimeDB.Unique] public uint __Id;", "__Id"), - ("User", "[SpacetimeDB.Unique] public uint Id; [SpacetimeDB.Unique] public uint IdUniqueIndex;", "IdUniqueIndex"), - ("User", "public uint UserCols;", "UserCols"), - ("User", "[SpacetimeDB.PrimaryKey] public uint UserIxCols;", "UserIxCols"), - ("Tables", "public uint Id;", "Tables"), - ("ReadOnlyTables", "public uint Id;", "ReadOnlyTables"), - ("Queries", "public uint Id;", "Queries"), - ("GetType", "public uint Id;", "GetType"), - }) + foreach ( + var (accessor, fields, symbol) in new[] + { + ("User", "[SpacetimeDB.Unique] public uint Count;", "Count"), + ( + "User", + "[SpacetimeDB.Unique] public uint Id; [SpacetimeDB.Unique] public uint __Id;", + "__Id" + ), + ( + "User", + "[SpacetimeDB.Unique] public uint Id; [SpacetimeDB.Unique] public uint IdUniqueIndex;", + "IdUniqueIndex" + ), + ("User", "public uint UserCols;", "UserCols"), + ("User", "[SpacetimeDB.PrimaryKey] public uint UserIxCols;", "UserIxCols"), + ("Tables", "public uint Id;", "Tables"), + ("ReadOnlyTables", "public uint Id;", "ReadOnlyTables"), + ("Queries", "public uint Id;", "Queries"), + ("GetType", "public uint Id;", "GetType"), + } + ) { - var (_, diagnostics) = Generate($$""" + var (_, diagnostics) = Generate( + $$""" [SpacetimeDB.Table(Accessor = "{{accessor}}")] public partial struct Row { {{fields}} } - """); + """ + ); Assert.DoesNotContain(diagnostics, d => d.Id == "CS8785"); - Assert.True(diagnostics.Any(d => d.GetMessage().Contains("Generated C# name") - && d.GetMessage().Contains(symbol) && d.Location.IsInSource), - $"Expected collision for {accessor}.{symbol}: {string.Join("\n", diagnostics)}"); + Assert.True( + diagnostics.Any(d => + d.GetMessage().Contains("Generated C# name") + && d.GetMessage().Contains(symbol) + && d.Location.IsInSource + ), + $"Expected collision for {accessor}.{symbol}: {string.Join("\n", diagnostics)}" + ); } - var (_, crossTableDiagnostics) = Generate(""" + var (_, crossTableDiagnostics) = Generate( + """ [SpacetimeDB.Table(Accessor = "User")] [SpacetimeDB.Table(Accessor = "UserIx")] public partial struct Row { public uint Id; } - """); - Assert.Contains(crossTableDiagnostics, d => d.GetMessage().Contains("UserIxCols") - && d.GetMessage().Contains("table 'User'") && d.GetMessage().Contains("table 'UserIx'")); + """ + ); + Assert.Contains( + crossTableDiagnostics, + d => + d.GetMessage().Contains("UserIxCols") + && d.GetMessage().Contains("table 'User'") + && d.GetMessage().Contains("table 'UserIx'") + ); - var (valid, validDiagnostics) = Generate(""" + var (valid, validDiagnostics) = Generate( + """ [SpacetimeDB.Table(Accessor = "First")] [SpacetimeDB.Table(Accessor = "Second")] public partial struct Row { [SpacetimeDB.Unique] public uint @class; } - """); + """ + ); Assert.Empty(validDiagnostics.Where(d => d.Severity == DiagnosticSeverity.Error)); using var dll = new MemoryStream(); var emitted = valid.Emit(dll); @@ -431,12 +524,20 @@ public static async Task TypeGeneratorOnClient() [InlineData(true, false)] [InlineData(false, true)] [InlineData(true, true)] - public static async Task NamespaceDependenciesRegisterOnceInStableOrder(bool rootHasTable, bool mounted) + public static async Task NamespaceDependenciesRegisterOnceInStableOrder( + bool rootHasTable, + bool mounted + ) { var fixture = await Fixture.Compile("server"); - const string usings = "global using System; global using System.IO; " + const string usings = + "global using System; global using System.IO; " + "global using System.Collections.Generic; global using System.Linq;\n"; - CSharpCompilation Create(string name, string source, params MetadataReference[] references) => + CSharpCompilation Create( + string name, + string source, + params MetadataReference[] references + ) => CSharpCompilation.Create( name, [CSharpSyntaxTree.ParseText(usings + source, fixture.ParseOptions)], @@ -446,7 +547,11 @@ CSharpCompilation Create(string name, string source, params MetadataReference[] CSharpCompilation Generate(CSharpCompilation input) { var driver = CSharpGeneratorDriver.Create( - [new Type().AsSourceGenerator(), new Module().AsSourceGenerator(), new EnvironmentGenerator().AsSourceGenerator()], + [ + new Type().AsSourceGenerator(), + new Module().AsSourceGenerator(), + new EnvironmentGenerator().AsSourceGenerator(), + ], parseOptions: fixture.ParseOptions ); driver.RunGeneratorsAndUpdateCompilation(input, out var output, out var diagnostics); @@ -461,59 +566,83 @@ MetadataReference Emit(CSharpCompilation compilation) Assert.True(result.Success, string.Join("\n", result.Diagnostics)); return MetadataReference.CreateFromImage(dll.ToArray()); } - string Table(string name) => $$""" - namespace {{name}} { - public class Sentinel { } - [SpacetimeDB.Table] - public partial struct {{name}}Row { public uint Id; } - } - """; - string Descriptor(CSharpCompilation compilation) => Assert.Single( - compilation.GetSymbolsWithName("AssemblyDescriptor", SymbolFilter.Type) - ).ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); - MethodDeclarationSyntax Method(CSharpCompilation compilation, string name) => Assert.Single( - compilation.SyntaxTrees.SelectMany(tree => tree.GetRoot().DescendantNodes()) - .OfType() - .Where(type => type.Identifier.ValueText == "ModuleRegistration") - .SelectMany(type => type.Members.OfType()) - .Where(method => method.Identifier.ValueText == name) - ); + string Table(string name) => + $$""" + namespace {{name}} { + public class Sentinel { } + [SpacetimeDB.Table] + public partial struct {{name}}Row { public uint Id; } + } + """; + string Descriptor(CSharpCompilation compilation) => + Assert + .Single(compilation.GetSymbolsWithName("AssemblyDescriptor", SymbolFilter.Type)) + .ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + MethodDeclarationSyntax Method(CSharpCompilation compilation, string name) => + Assert.Single( + compilation + .SyntaxTrees.SelectMany(tree => tree.GetRoot().DescendantNodes()) + .OfType() + .Where(type => type.Identifier.ValueText == "ModuleRegistration") + .SelectMany(type => type.Members.OfType()) + .Where(method => method.Identifier.ValueText == name) + ); var sharedCompilation = Generate(Create("Shared", Table("Shared"))); var shared = Emit(sharedCompilation); - var alphaCompilation = Generate(Create("Alpha", Table("Alpha") - + "public class AlphaLink { public Shared.Sentinel Value; }", shared)); + var alphaCompilation = Generate( + Create( + "Alpha", + Table("Alpha") + "public class AlphaLink { public Shared.Sentinel Value; }", + shared + ) + ); var alpha = Emit(alphaCompilation); - var betaCompilation = Generate(Create("Beta", Table("Beta") - + "public class BetaLink { public Shared.Sentinel Value; }", shared)); + var betaCompilation = Generate( + Create( + "Beta", + Table("Beta") + "public class BetaLink { public Shared.Sentinel Value; }", + shared + ) + ); var beta = Emit(betaCompilation); - var utility = Emit(Create("Utility", - "public class UtilityLink { public Shared.Sentinel Value; }", shared)); + var utility = Emit( + Create("Utility", "public class UtilityLink { public Shared.Sentinel Value; }", shared) + ); var rootSource = rootHasTable ? Table("Root") : ""; if (mounted) - rootSource = "[assembly: SpacetimeDB.Namespace(typeof(Alpha.Sentinel), Accessor = \"Auth\")]\n" + rootSource = + "[assembly: SpacetimeDB.Namespace(typeof(Alpha.Sentinel), Accessor = \"Auth\")]\n" + "[assembly: SpacetimeDB.Namespace(typeof(Beta.Sentinel), Accessor = \"class\")]\n" + rootSource; var root = Generate(Create("Root", rootSource, beta, utility, shared, alpha)); var reordered = Generate(Create("Root", rootSource, alpha, shared, utility, beta)); string[] Calls(CSharpCompilation compilation) => - [.. Method(compilation, "Initialize").DescendantNodes() - .OfType() - .Select(call => call.Expression.ToString()) - .Where(call => call.EndsWith(".Register"))]; + [ + .. Method(compilation, "Initialize") + .DescendantNodes() + .OfType() + .Select(call => call.Expression.ToString()) + .Where(call => call.EndsWith(".Register")), + ]; CSharpCompilation[] orderedDependencies = mounted ? [sharedCompilation, alphaCompilation, betaCompilation] : [alphaCompilation, betaCompilation, sharedCompilation]; var expected = new[] { Descriptor(root) + ".Register" } - .Concat(orderedDependencies.Select(c => Descriptor(c) + ".Register")).ToArray(); + .Concat(orderedDependencies.Select(c => Descriptor(c) + ".Register")) + .ToArray(); if (mounted) { var init = Method(root, "Initialize"); - var submodules = init.DescendantNodes().OfType() - .Where(call => call.Expression.ToString().EndsWith(".RegisterSubmodule")).ToArray(); - Assert.Equal(["\"Auth\"", "\"class\""], - submodules.Select(call => call.ArgumentList.Arguments[0].ToString())); + var submodules = init.DescendantNodes() + .OfType() + .Where(call => call.Expression.ToString().EndsWith(".RegisterSubmodule")) + .ToArray(); + Assert.Equal( + ["\"Auth\"", "\"class\""], + submodules.Select(call => call.ArgumentList.Arguments[0].ToString()) + ); } Assert.Equal(expected, Calls(root)); Assert.Equal(expected, Calls(reordered)); @@ -526,89 +655,152 @@ [.. Method(compilation, "Initialize").DescendantNodes() var empty = Generate(Create("Empty", "", plainUtility)); Assert.Empty(empty.GetSymbolsWithName("AssemblyDescriptor", SymbolFilter.Type)); - var nested = Emit(Generate(Create("Nested", - "[assembly: SpacetimeDB.Namespace(typeof(Alpha.Sentinel), Accessor = \"Auth\")]", - alpha, shared))); - var nestedResult = CSharpGeneratorDriver.Create( - [new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions - ).RunGenerators(Create("Outer", "", nested, alpha, shared)).GetRunResult(); - Assert.Contains(nestedResult.Diagnostics, diagnostic => - diagnostic.GetMessage().Contains("Only the consuming root")); + var nested = Emit( + Generate( + Create( + "Nested", + "[assembly: SpacetimeDB.Namespace(typeof(Alpha.Sentinel), Accessor = \"Auth\")]", + alpha, + shared + ) + ) + ); + var nestedResult = CSharpGeneratorDriver + .Create([new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions) + .RunGenerators(Create("Outer", "", nested, alpha, shared)) + .GetRunResult(); + Assert.Contains( + nestedResult.Diagnostics, + diagnostic => diagnostic.GetMessage().Contains("Only the consuming root") + ); foreach (var kind in new[] { "Init", "ClientConnected", "ClientDisconnected" }) { - var lifecycle = Emit(Generate(Create("LifecycleDependency", $$""" - public class Marker { } - public static partial class LifecycleFunctions { - [SpacetimeDB.Reducer(SpacetimeDB.ReducerKind.{{kind}})] - public static void Handle(SpacetimeDB.ReducerContext ctx) { } - } - """))); - var lifecycleResult = CSharpGeneratorDriver.Create( - [new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions - ).RunGenerators(Create("LifecycleConsumer", - "[assembly: SpacetimeDB.Namespace(typeof(Marker), Accessor = \"Auth\")]", - lifecycle)).GetRunResult(); - Assert.Contains(lifecycleResult.Diagnostics, diagnostic => - diagnostic.Severity == DiagnosticSeverity.Error - && diagnostic.Descriptor.Title.ToString() == "Root-only declarations in mounted dependency" - && diagnostic.GetMessage().Contains("LifecycleFunctions.Handle (" + kind + ")") - && diagnostic.GetMessage().Contains("Auth")); + var lifecycle = Emit( + Generate( + Create( + "LifecycleDependency", + $$""" + public class Marker { } + public static partial class LifecycleFunctions { + [SpacetimeDB.Reducer(SpacetimeDB.ReducerKind.{{kind}})] + public static void Handle(SpacetimeDB.ReducerContext ctx) { } + } + """ + ) + ) + ); + var lifecycleResult = CSharpGeneratorDriver + .Create([new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions) + .RunGenerators( + Create( + "LifecycleConsumer", + "[assembly: SpacetimeDB.Namespace(typeof(Marker), Accessor = \"Auth\")]", + lifecycle + ) + ) + .GetRunResult(); + Assert.Contains( + lifecycleResult.Diagnostics, + diagnostic => + diagnostic.Severity == DiagnosticSeverity.Error + && diagnostic.Descriptor.Title.ToString() + == "Root-only declarations in mounted dependency" + && diagnostic.GetMessage().Contains("LifecycleFunctions.Handle (" + kind + ")") + && diagnostic.GetMessage().Contains("Auth") + ); // The same dependency can still be published alone or merged into the root scope. Generate(Create("FlatLifecycleConsumer", "", lifecycle)); - Generate(Create("PublicLifecycleConsumer", - "[assembly: SpacetimeDB.Namespace(typeof(Marker), Accessor = \"public\")]", - lifecycle)); + Generate( + Create( + "PublicLifecycleConsumer", + "[assembly: SpacetimeDB.Namespace(typeof(Marker), Accessor = \"public\")]", + lifecycle + ) + ); } - foreach (var (source, declaration) in new[] - { - (""" - #pragma warning disable STDB_UNSTABLE - public static class Rules { - [SpacetimeDB.ClientVisibilityFilter] - public static readonly SpacetimeDB.Filter Visible = - new SpacetimeDB.Filter.Sql("SELECT * FROM Entry"); - } - """, "row-level security filters"), - ("[SpacetimeDB.Env] public struct Settings { public string SECRET; }", "environment variables"), - }) + foreach ( + var (source, declaration) in new[] + { + ( + "#pragma warning disable STDB_UNSTABLE\n" + + """ + public static class Rules { + [SpacetimeDB.ClientVisibilityFilter] + public static readonly SpacetimeDB.Filter Visible = + new SpacetimeDB.Filter.Sql("SELECT * FROM Entry"); + } + """, + "row-level security filters" + ), + ( + "[SpacetimeDB.Env] public struct Settings { public string SECRET; }", + "environment variables" + ), + } + ) { - var dependency = Emit(Generate(Create("RestrictedDependency", - "[SpacetimeDB.Table] public partial struct Entry { public uint Id; }\n" + source))); - var result = CSharpGeneratorDriver.Create( - [new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions - ).RunGenerators(Create("RestrictedConsumer", - "[assembly: SpacetimeDB.Namespace(typeof(Entry), Accessor = \"Auth\")]", - dependency)).GetRunResult(); - Assert.Contains(result.Diagnostics, diagnostic => - diagnostic.Severity == DiagnosticSeverity.Error - && diagnostic.GetMessage().Contains("RestrictedDependency") - && diagnostic.GetMessage().Contains("'Auth'") - && diagnostic.GetMessage().Contains(declaration) - && diagnostic.GetMessage().Contains("root scope")); + var dependency = Emit( + Generate( + Create( + "RestrictedDependency", + "[SpacetimeDB.Table] public partial struct Entry { public uint Id; }\n" + + source + ) + ) + ); + var result = CSharpGeneratorDriver + .Create([new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions) + .RunGenerators( + Create( + "RestrictedConsumer", + "[assembly: SpacetimeDB.Namespace(typeof(Entry), Accessor = \"Auth\")]", + dependency + ) + ) + .GetRunResult(); + Assert.Contains( + result.Diagnostics, + diagnostic => + diagnostic.Severity == DiagnosticSeverity.Error + && diagnostic.GetMessage().Contains("RestrictedDependency") + && diagnostic.GetMessage().Contains("'Auth'") + && diagnostic.GetMessage().Contains(declaration) + && diagnostic.GetMessage().Contains("root scope") + ); Generate(Create("FlatConsumer", "", dependency)); - Generate(Create("PublicConsumer", - "[assembly: SpacetimeDB.Namespace(typeof(Entry), Accessor = \"public\")]", - dependency)); + Generate( + Create( + "PublicConsumer", + "[assembly: SpacetimeDB.Namespace(typeof(Entry), Accessor = \"public\")]", + dependency + ) + ); } // Empty environment schemas contain no keys and are permitted by the host. - var emptyEnvironment = Emit(Generate(Create("EmptyEnvironment", - "[SpacetimeDB.Env] public struct Settings { }"))); - Generate(Create("EmptyEnvironmentConsumer", - "[assembly: SpacetimeDB.Namespace(typeof(Settings), Accessor = \"Auth\")]", - emptyEnvironment)); + var emptyEnvironment = Emit( + Generate(Create("EmptyEnvironment", "[SpacetimeDB.Env] public struct Settings { }")) + ); + Generate( + Create( + "EmptyEnvironmentConsumer", + "[assembly: SpacetimeDB.Namespace(typeof(Settings), Accessor = \"Auth\")]", + emptyEnvironment + ) + ); } - #endif [Fact] public static async Task TypeAndModuleGeneratorsOnServer() { var fixture = await Fixture.Compile("server"); - await fixture.Verify(nameof(EnvironmentGenerator), - fixture.RunGeneratorAndGetResult(new EnvironmentGenerator())); + await fixture.Verify( + nameof(EnvironmentGenerator), + fixture.RunGeneratorAndGetResult(new EnvironmentGenerator()) + ); var compilationAfterGen = await fixture.RunAndCheckGenerators( new SpacetimeDB.Codegen.Type(), diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/Lib.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/Lib.cs index ff2673215e0..fd6945985f3 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/Lib.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/Lib.cs @@ -9,6 +9,7 @@ public struct EnvironmentSchema { public string REQUIRED; public string? OPTIONAL; + [SpacetimeDB.EnvValues("dev", "prod")] public string MODE; } diff --git a/crates/bindings-csharp/Codegen/Diag.cs b/crates/bindings-csharp/Codegen/Diag.cs index 6a5d7423e95..4bcd0ba05f8 100644 --- a/crates/bindings-csharp/Codegen/Diag.cs +++ b/crates/bindings-csharp/Codegen/Diag.cs @@ -361,19 +361,29 @@ string type $"View '{ctx.method.Identifier}' declares primary key '{ctx.primaryKey}', but its type '{ctx.type}' is not supported for view primary keys.", ctx => ctx.primaryKeySyntax ); - public static readonly ErrorDescriptor<(AttributeData attribute, string message)> InvalidNamespace = - new( - group, - "Invalid namespace mount", - ctx => $"{ctx.message}", - ctx => ctx.attribute - ); - public static readonly ErrorDescriptor<(string accessor, string first, string second)> NamespaceAccessorCollision = + public static readonly ErrorDescriptor<( + ISymbol symbol, + string message + )> InvalidEnvironmentDeclaration = + new(group, "Invalid environment declaration", ctx => $"{ctx.message}", ctx => ctx.symbol); + + public static readonly ErrorDescriptor<( + AttributeData attribute, + string message + )> InvalidNamespace = + new(group, "Invalid namespace mount", ctx => $"{ctx.message}", ctx => ctx.attribute); + + public static readonly ErrorDescriptor<( + string accessor, + string first, + string second + )> NamespaceAccessorCollision = new( group, "Conflicting module accessors", - ctx => $"Accessor '{ctx.accessor}' is contributed by both '{ctx.first}' and '{ctx.second}'. Mount the conflicting dependency with a distinct accessor.", + ctx => + $"Accessor '{ctx.accessor}' is contributed by both '{ctx.first}' and '{ctx.second}'. Mount the conflicting dependency with a distinct accessor.", _ => Location.None ); @@ -381,23 +391,36 @@ string type new( group, "Dependency declares namespace mounts", - identity => $"Dependency '{identity}' declares namespace mounts. Only the consuming root may choose dependency placement; move those declarations to the root.", + identity => + $"Dependency '{identity}' declares namespace mounts. Only the consuming root may choose dependency placement; move those declarations to the root.", _ => Location.None ); - public static readonly ErrorDescriptor<(string assembly, string name, string declarations)> MountedRootOnlyDeclarations = + public static readonly ErrorDescriptor<( + string assembly, + string name, + string declarations + )> MountedRootOnlyDeclarations = new( group, "Root-only declarations in mounted dependency", - ctx => $"Dependency '{ctx.assembly}' mounted in namespace '{ctx.name}' declares {ctx.declarations}. These declarations are only supported in the root scope. Move them to the root, or omit the namespace declaration so the dependency registers automatically in public. Root-defined RLS may target namespace-qualified tables.", + ctx => + $"Dependency '{ctx.assembly}' mounted in namespace '{ctx.name}' declares {ctx.declarations}. These declarations are only supported in the root scope. Move them to the root, or omit the namespace declaration so the dependency registers automatically in public. Root-defined RLS may target namespace-qualified tables.", _ => Location.None ); - public static readonly ErrorDescriptor<(Location location, string scope, string name, string first, string second)> GeneratedNameCollision = + public static readonly ErrorDescriptor<( + Location location, + string scope, + string name, + string first, + string second + )> GeneratedNameCollision = new( group, "Conflicting generated C# names", - ctx => $"Generated C# name '{ctx.scope}.{ctx.name}' is used by both {ctx.first} and {ctx.second}. Choose distinct accessors or member names.", + ctx => + $"Generated C# name '{ctx.scope}.{ctx.name}' is used by both {ctx.first} and {ctx.second}. Choose distinct accessors or member names.", ctx => ctx.location ); } diff --git a/crates/bindings-csharp/Codegen/Environment.cs b/crates/bindings-csharp/Codegen/Environment.cs index 92f75ba8500..b8dce6ee34b 100644 --- a/crates/bindings-csharp/Codegen/Environment.cs +++ b/crates/bindings-csharp/Codegen/Environment.cs @@ -13,16 +13,6 @@ namespace SpacetimeDB.Codegen; [Generator] public sealed class EnvironmentGenerator : IIncrementalGenerator { - private static readonly DiagnosticDescriptor InvalidDeclaration = - new( - "STDBENV001", - "Invalid environment declaration", - "{0}", - "SpacetimeDB", - DiagnosticSeverity.Error, - isEnabledByDefault: true - ); - public void Initialize(IncrementalGeneratorInitializationContext context) { var declarations = Declarations(context); @@ -173,11 +163,7 @@ string assemblyNamespace sharedContexts, (symbol, message) => context.ReportDiagnostic( - Diagnostic.Create( - InvalidDeclaration, - symbol.Locations.FirstOrDefault(), - message - ) + ErrorDescriptor.InvalidEnvironmentDeclaration.ToDiag((symbol, message)) ) ); if (sharedContexts) diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index a25fa0824aa..c62d7ccffbf 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -500,30 +500,32 @@ record TableDeclaration : BaseTypeDeclaration private string TableHandlesNamespace => handlesNamespace + ".TableHandles"; private string ViewHandlesNamespace => handlesNamespace + ".ViewHandles"; - private string LookupName(string localName) => sharedContexts - ? $"global::SpacetimeDB.Internal.Module.ResolveName({SymbolDisplay.FormatLiteral(assemblyIdentity, true)}, {SymbolDisplay.FormatLiteral(localName, true)})" - : SymbolDisplay.FormatLiteral(localName, true); + private string LookupName(string localName) => + sharedContexts + ? $"global::SpacetimeDB.Internal.Module.ResolveName({SymbolDisplay.FormatLiteral(assemblyIdentity, true)}, {SymbolDisplay.FormatLiteral(localName, true)})" + : SymbolDisplay.FormatLiteral(localName, true); private string HandleLookupName(string localName) => sharedContexts ? "__resolvedName" : LookupName(localName); - private string HandleLookupNameCache(string typeName, string localName) => sharedContexts - ? $$""" - private static readonly string __resolvedName = {{LookupName(localName)}}; - // Prevent eager initialization before the root installs namespace placements. - static {{typeName}}() { } - """ - : ""; - - private string IndexInstanceCache(string typeName, string identifier) => sharedContexts - ? $$""" - private static {{typeName}}? __{{identifier.TrimStart('@')}}; - """ - : ""; - - private string IndexInstance(string identifier) => sharedContexts - ? $"__{identifier.TrimStart('@')} ??= new()" - : "new()"; + private string HandleLookupNameCache(string typeName, string localName) => + sharedContexts + ? $$""" + private static readonly string __resolvedName = {{LookupName(localName)}}; + // Prevent eager initialization before the root installs namespace placements. + static {{typeName}}() { } + """ + : ""; + + private string IndexInstanceCache(string typeName, string identifier) => + sharedContexts + ? $$""" + private static {{typeName}}? __{{identifier.TrimStart('@')}}; + """ + : ""; + + private string IndexInstance(string identifier) => + sharedContexts ? $"__{identifier.TrimStart('@')} ??= new()" : "new()"; public int? GetColumnIndex(AttributeData attrContext, string name, DiagReporter diag) { @@ -546,7 +548,9 @@ public TableDeclaration(GeneratorAttributeSyntaxContext context, DiagReporter di var compilation = context.SemanticModel.Compilation; assemblyIdentity = compilation.Assembly.Identity.ToString(); sharedContexts = Module.UsesSharedContexts(compilation); - handlesNamespace = sharedContexts ? Module.AssemblyNamespace(compilation.Assembly) : "SpacetimeDB.Internal"; + handlesNamespace = sharedContexts + ? Module.AssemblyNamespace(compilation.Assembly) + : "SpacetimeDB.Internal"; isRowStruct = ((INamedTypeSymbol)context.TargetSymbol).IsValueType; @@ -596,8 +600,13 @@ public TableDeclaration(GeneratorAttributeSyntaxContext context, DiagReporter di private void ValidateGeneratedNames(DiagReporter diag, Location location) { - var names = new GeneratedNames((scope, name, first, second) => - diag.Report(ErrorDescriptor.GeneratedNameCollision, (location, scope, name, first, second))); + var names = new GeneratedNames( + (scope, name, first, second) => + diag.Report( + ErrorDescriptor.GeneratedNameCollision, + (location, scope, name, first, second) + ) + ); foreach (var table in TableAccessors) { var owner = $"table '{table.Name}' on '{FullName}'"; @@ -605,7 +614,20 @@ private void ValidateGeneratedNames(DiagReporter diag, Location location) var readOnly = $"{ViewHandlesNamespace}.{table.Name}ReadOnly"; names.Add(writable, table.Identifier, "enclosing table handle"); names.Add(readOnly, table.Identifier + "ReadOnly", "enclosing read-only handle"); - foreach (var member in new[] { "LookupName", "ReadGenFields", "MakeTableDesc", "MakeScheduleDesc", "Count", "Iter", "Insert", "Delete", "Clear" }) + foreach ( + var member in new[] + { + "LookupName", + "ReadGenFields", + "MakeTableDesc", + "MakeScheduleDesc", + "Count", + "Iter", + "Insert", + "Delete", + "Clear", + } + ) names.Add(writable, member, "generated table member"); foreach (var member in new[] { "__resolvedName", "Count", "Iter" }) names.Add(readOnly, member, "generated read-only table member"); @@ -615,13 +637,27 @@ void Index(string identifier, bool unique, string contributor) foreach (var scope in new[] { writable, readOnly }) { names.Add(scope, identifier, contributor); - names.Add(scope, "__" + identifier.TrimStart('@'), $"cache field for {contributor}"); - names.Add(scope, identifier + (unique && scope == writable ? "UniqueIndex" : "Index"), - $"index type for {contributor}"); + names.Add( + scope, + "__" + identifier.TrimStart('@'), + $"cache field for {contributor}" + ); + names.Add( + scope, + identifier + (unique && scope == writable ? "UniqueIndex" : "Index"), + $"index type for {contributor}" + ); } } - foreach (var constraint in GetConstraints(table, ColumnAttrs.Unique).Where(c => c.Col.IsEquatable)) - Index(constraint.Col.Identifier, true, $"unique column '{constraint.Col.Name}' of {owner}"); + foreach ( + var constraint in GetConstraints(table, ColumnAttrs.Unique) + .Where(c => c.Col.IsEquatable) + ) + Index( + constraint.Col.Identifier, + true, + $"unique column '{constraint.Col.Name}' of {owner}" + ); foreach (var index in GetIndexes(table).Where(i => i.AccessorName.Length != 0)) Index(index.AccessorIdentifier, false, $"index '{index.AccessorName}' of {owner}"); @@ -631,8 +667,16 @@ void Index(string identifier, bool unique, string contributor) foreach (var container in new[] { "Tables", "ReadOnlyTables", "Queries" }) names.Add(container, table.Identifier, owner); if (table.Name is "GetType" or "ToString" or "Equals" or "GetHashCode") - diag.Report(ErrorDescriptor.GeneratedNameCollision, - (location, "context database/query receiver", table.Name, "existing receiver member", owner)); + diag.Report( + ErrorDescriptor.GeneratedNameCollision, + ( + location, + "context database/query receiver", + table.Name, + "existing receiver member", + owner + ) + ); var cols = table.Identifier + "Cols"; names.Add(cols, cols, "enclosing query columns type"); foreach (var column in Members) @@ -640,10 +684,12 @@ void Index(string identifier, bool unique, string contributor) var ixCols = table.Identifier + "IxCols"; names.Add(ixCols, ixCols, "enclosing indexed query columns type"); var indexedPositions = new HashSet( - GetConstraints(table, ColumnAttrs.PrimaryKey | ColumnAttrs.Unique).Select(c => c.Pos)); + GetConstraints(table, ColumnAttrs.PrimaryKey | ColumnAttrs.Unique) + .Select(c => c.Pos) + ); foreach (var index in GetIndexes(table)) - foreach (var column in index.Columns.Array) - indexedPositions.Add(column.Index); + foreach (var column in index.Columns.Array) + indexedPositions.Add(column.Index); foreach (var position in indexedPositions) { var column = Members[position]; @@ -663,7 +709,8 @@ public IEnumerable GenerateTableAccessorFilters(TableAccessor tableAcces var vis = SyntaxFacts.GetText(Visibility); var globalName = $"global::{FullName}"; - var uniqueIndexBase = "global::SpacetimeDB.Internal." + (isRowStruct ? "UniqueIndex" : "RefUniqueIndex"); + var uniqueIndexBase = + "global::SpacetimeDB.Internal." + (isRowStruct ? "UniqueIndex" : "RefUniqueIndex"); foreach (var ct in GetConstraints(tableAccessor, ColumnAttrs.Unique)) { @@ -681,7 +728,9 @@ public IEnumerable GenerateTableAccessorFilters(TableAccessor tableAcces yield return $$""" {{vis}} sealed class {{f.Identifier}}UniqueIndex : {{uniqueIndexBase}}<{{tableAccessor.Identifier}}, {{globalName}}, {{f.Type.Name}}, {{f.Type.BSATNName}}> { {{HandleLookupNameCache(f.Identifier + "UniqueIndex", standardIndexName)}} - internal {{f.Identifier}}UniqueIndex() : base({{HandleLookupName(standardIndexName)}}) {} + internal {{f.Identifier}}UniqueIndex() : base({{HandleLookupName( + standardIndexName + )}}) {} // Important: don't move this to the base class. // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. @@ -689,7 +738,9 @@ public IEnumerable GenerateTableAccessorFilters(TableAccessor tableAcces {{updateMethod}} } {{IndexInstanceCache(f.Identifier + "UniqueIndex", f.Identifier)}} - {{vis}} {{f.Identifier}}UniqueIndex {{f.Identifier}} => {{IndexInstance(f.Identifier)}}; + {{vis}} {{f.Identifier}}UniqueIndex {{f.Identifier}} => {{IndexInstance( + f.Identifier + )}}; """; } @@ -709,7 +760,9 @@ public IEnumerable GenerateTableAccessorFilters(TableAccessor tableAcces var standardIndexName = index.StandardIndexName(tableAccessor); yield return $$""" - {{vis}} sealed class {{identifierName}}Index() : SpacetimeDB.Internal.IndexBase<{{globalName}}>({{HandleLookupName(standardIndexName)}}) { + {{vis}} sealed class {{identifierName}}Index() : SpacetimeDB.Internal.IndexBase<{{globalName}}>({{HandleLookupName( + standardIndexName + )}}) { {{HandleLookupNameCache(identifierName + "Index", standardIndexName)}} """; @@ -785,13 +838,17 @@ public sealed class {{{f.Identifier}}}Index {{{f.Type.BSATNName}}}> { {{{HandleLookupNameCache(f.Identifier + "Index", standardIndexName)}}} - internal {{{f.Identifier}}}Index() : base({{{HandleLookupName(standardIndexName)}}}) { } + internal {{{f.Identifier}}}Index() : base({{{HandleLookupName( + standardIndexName + )}}}) { } public {{{globalName}}}? Find({{{f.Type.Name}}} key) => FindSingle(key); } {{{IndexInstanceCache(f.Identifier + "Index", f.Identifier)}}} - public {{{f.Identifier}}}Index {{{f.Identifier}}} => {{{IndexInstance(f.Identifier)}}}; + public {{{f.Identifier}}}Index {{{f.Identifier}}} => {{{IndexInstance( + f.Identifier + )}}}; """; } @@ -814,7 +871,9 @@ public sealed class {{{identifierName}}}Index : global::SpacetimeDB.Internal.ReadOnlyIndexBase<{{{globalName}}}> { {{{HandleLookupNameCache(identifierName + "Index", standardIndexName)}}} - internal {{{identifierName}}}Index() : base({{{HandleLookupName(standardIndexName)}}}) {} + internal {{{identifierName}}}Index() : base({{{HandleLookupName( + standardIndexName + )}}}) {} """, }; @@ -858,7 +917,9 @@ public sealed class {{{identifierName}}}Index ); } - blocks.Add($"}}\n{IndexInstanceCache(identifierName + "Index", identifierName)}\n{vis} {identifierName}Index {identifierName} => {IndexInstance(identifierName)};"); + blocks.Add( + $"}}\n{IndexInstanceCache(identifierName + "Index", identifierName)}\n{vis} {identifierName}Index {identifierName} => {IndexInstance(identifierName)};" + ); yield return string.Join("\n", blocks); } } @@ -996,7 +1057,9 @@ public IEnumerable GenerateReadOnlyAccessors() : global::SpacetimeDB.Internal.ReadOnlyTableView<{{{globalName}}}> { {{{HandleLookupNameCache(accessorIdentifier + "ReadOnly", accessor.Name)}}} - internal {{{accessorIdentifier}}}ReadOnly() : base({{{HandleLookupName(accessor.Name)}}}) { } + internal {{{accessorIdentifier}}}ReadOnly() : base({{{HandleLookupName( + accessor.Name + )}}}) { } /// /// Returns the number of rows in this table. @@ -1090,7 +1153,8 @@ string IxColInit(ColumnDeclaration col) var ixColsDecls = string.Join("\n ", ixMembers.Select(IxColDecl)); var ixColsInits = string.Join("\n ", ixMembers.Select(IxColInit)); var nameType = useExtensions ? "global::SpacetimeDB.SqlTableName" : "string"; - var queryType = $"global::SpacetimeDB.Table<{globalRowName}, {colsTypeName}, {ixColsTypeName}>"; + var queryType = + $"global::SpacetimeDB.Table<{globalRowName}, {colsTypeName}, {ixColsTypeName}>"; var queryMember = useExtensions ? $$""" public static partial class AssemblyDescriptor @@ -1098,7 +1162,10 @@ public static partial class AssemblyDescriptor private static class {{accessorIdentifier}}SqlNameCache { internal static readonly global::SpacetimeDB.SqlTableName Name = - global::SpacetimeDB.Internal.Module.ResolveSqlName({{SymbolDisplay.FormatLiteral(assemblyIdentity, true)}}, {{SymbolDisplay.FormatLiteral(tableName, true)}}); + global::SpacetimeDB.Internal.Module.ResolveSqlName({{SymbolDisplay.FormatLiteral( + assemblyIdentity, + true + )}}, {{SymbolDisplay.FormatLiteral(tableName, true)}}); // Prevent eager initialization before the root installs namespace placements. static {{accessorIdentifier}}SqlNameCache() { } } @@ -1129,7 +1196,6 @@ public readonly partial struct QueryBuilder } """; - yield return $$""" {{vis}} readonly struct {{colsTypeName}} { @@ -1654,7 +1720,8 @@ record ReducerDeclaration public ReducerDeclaration(GeneratorAttributeSyntaxContext context, DiagReporter diag) { declaringAssembly = Module.UsesSharedContexts(context.SemanticModel.Compilation) - ? context.SemanticModel.Compilation.Assembly.Identity.ToString() : null; + ? context.SemanticModel.Compilation.Assembly.Identity.ToString() + : null; var methodSyntax = (MethodDeclarationSyntax)context.TargetNode; var method = (IMethodSymbol)context.TargetSymbol; var attr = context.Attributes.Single().ParseAs(); @@ -1741,15 +1808,20 @@ public Scope.Extensions GenerateSchedule() if (declaringAssembly is not null) { var cacheName = $"__Schedule{Name}Name"; - extensions.Contents.Append($$""" + extensions.Contents.Append( + $$""" private static class {{cacheName}} { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName({{SymbolDisplay.FormatLiteral(declaringAssembly, true)}}, {{functionName}}); + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName({{SymbolDisplay.FormatLiteral( + declaringAssembly, + true + )}}, {{functionName}}); // Prevent eager initialization before the root installs namespace placements. static {{cacheName}}() { } } - - """); + + """ + ); functionName = cacheName + ".Name"; } @@ -1801,7 +1873,8 @@ record ProcedureDeclaration public ProcedureDeclaration(GeneratorAttributeSyntaxContext context, DiagReporter diag) { declaringAssembly = Module.UsesSharedContexts(context.SemanticModel.Compilation) - ? context.SemanticModel.Compilation.Assembly.Identity.ToString() : null; + ? context.SemanticModel.Compilation.Assembly.Identity.ToString() + : null; var methodSyntax = (MethodDeclarationSyntax)context.TargetNode; var method = (IMethodSymbol)context.TargetSymbol; var attr = context.Attributes.Single().ParseAs(); @@ -1982,15 +2055,20 @@ public Scope.Extensions GenerateSchedule() if (declaringAssembly is not null) { var cacheName = $"__Schedule{Name}Name"; - extensions.Contents.Append($$""" + extensions.Contents.Append( + $$""" private static class {{cacheName}} { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName({{SymbolDisplay.FormatLiteral(declaringAssembly, true)}}, {{functionName}}); + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName({{SymbolDisplay.FormatLiteral( + declaringAssembly, + true + )}}, {{functionName}}); // Prevent eager initialization before the root installs namespace placements. static {{cacheName}}() { } } - - """); + + """ + ); functionName = cacheName + ".Name"; } @@ -2208,9 +2286,11 @@ EquatableArray Queries public class Module : IIncrementalGenerator { internal static bool UsesSharedContexts(Compilation compilation) => - compilation.SyntaxTrees.Any(tree => tree.Options is CSharpParseOptions options - && options.PreprocessorSymbolNames.Contains("NET10_0_OR_GREATER")); - + compilation.SyntaxTrees.Any(tree => + tree.Options is CSharpParseOptions options + && options.PreprocessorSymbolNames.Contains("NET10_0_OR_GREATER") + ); + internal static string AssemblyNamespace(IAssemblySymbol assembly) { var name = Regex.Replace(assembly.Name, @"[^A-Za-z0-9_]", "_"); @@ -2224,9 +2304,7 @@ internal static string AssemblyNamespace(IAssemblySymbol assembly) var hash = sha256.ComputeHash( System.Text.Encoding.UTF8.GetBytes(assembly.Identity.ToString()) ); - var suffix = string.Concat( - hash.Take(8).Select(b => b.ToString("X2")) - ); + var suffix = string.Concat(hash.Take(8).Select(b => b.ToString("X2"))); return $"SpacetimeDB.Generated.{name}_{suffix}"; } @@ -2257,7 +2335,9 @@ tree.Options is CSharpParseOptions options } var visited = new HashSet { compilation.Assembly.Identity }; - var pending = new Stack(compilation.SourceModule.ReferencedAssemblySymbols); + var pending = new Stack( + compilation.SourceModule.ReferencedAssemblySymbols + ); var assemblies = new List(); while (pending.Count > 0) { @@ -2277,9 +2357,11 @@ tree.Options is CSharpParseOptions options } } - var marker = assembly.GetAttributes().FirstOrDefault(attribute => - SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, markerType) - ); + var marker = assembly + .GetAttributes() + .FirstOrDefault(attribute => + SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, markerType) + ); if ( marker is null || marker.ConstructorArguments.Length != 1 @@ -2294,37 +2376,61 @@ marker is null new AssemblyDeclaration( assembly.Identity.ToString(), descriptor.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat), - assembly.GetAttributes().Any(attribute => - attribute.AttributeClass?.ToDisplayString() == "SpacetimeDB.NamespaceAttribute"), - descriptor.GetMembers("RootOnlyDeclarations").OfType() - .FirstOrDefault()?.ConstantValue as string ?? "", + assembly + .GetAttributes() + .Any(attribute => + attribute.AttributeClass?.ToDisplayString() + == "SpacetimeDB.NamespaceAttribute" + ), + descriptor + .GetMembers("RootOnlyDeclarations") + .OfType() + .FirstOrDefault() + ?.ConstantValue as string + ?? "", ReadAccessors("Tables"), ReadAccessors("ReadOnlyTables"), - new(descriptor.GetTypeMembers("Queries").SelectMany(type => type.GetMembers()) - .OfType() - .Where(method => method.DeclaredAccessibility == Accessibility.Public - && method.MethodKind == MethodKind.Ordinary && method.Parameters.IsEmpty - && !method.IsStatic) - .Select(method => new AssemblyTableAccessor( - method.Name, - method.ReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) - )).ToImmutableArray()) + new( + descriptor + .GetTypeMembers("Queries") + .SelectMany(type => type.GetMembers()) + .OfType() + .Where(method => + method.DeclaredAccessibility == Accessibility.Public + && method.MethodKind == MethodKind.Ordinary + && method.Parameters.IsEmpty + && !method.IsStatic + ) + .Select(method => new AssemblyTableAccessor( + method.Name, + method.ReturnType.ToDisplayString( + SymbolDisplayFormat.FullyQualifiedFormat + ) + )) + .ToImmutableArray() + ) ) ); - EquatableArray ReadAccessors(string container) => new( - descriptor.GetTypeMembers(container).SelectMany(type => type.GetMembers()) - .OfType() - .Where(property => property.DeclaredAccessibility == Accessibility.Public) - .Select(property => new AssemblyTableAccessor( - property.Name, - property.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) - )).ToImmutableArray() - ); + EquatableArray ReadAccessors(string container) => + new( + descriptor + .GetTypeMembers(container) + .SelectMany(type => type.GetMembers()) + .OfType() + .Where(property => property.DeclaredAccessibility == Accessibility.Public) + .Select(property => new AssemblyTableAccessor( + property.Name, + property.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + )) + .ToImmutableArray() + ); } return new( - assemblies.OrderBy(assembly => assembly.Identity, StringComparer.Ordinal).ToImmutableArray() + assemblies + .OrderBy(assembly => assembly.Identity, StringComparer.Ordinal) + .ToImmutableArray() ); } @@ -2587,7 +2693,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context) "Reducer", context, reducers - .Select((r, ct) => (r.Name, r.FullName, r.CanonicalName, r.Kind, Class: r.GenerateClass())) + .Select( + (r, ct) => + (r.Name, r.FullName, r.CanonicalName, r.Kind, Class: r.GenerateClass()) + ) .WithTrackingName("SpacetimeDB.Reducer.GenerateClass"), r => r.Name, r => r.FullName @@ -2716,38 +2825,59 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Combine(columnDefaultValues) .Select((tuple, ct) => FlattenModuleOutputInputs(tuple)); - var environment = EnvironmentGenerator.Declarations(context).Select((types, _) => ( - HasDeclarations: types.Length != 0, - Registrations: EnvironmentGenerator.RegistrationCode(types) - )); - var extensionNamespace = context.CompilationProvider.Select( - (compilation, _) => ( - Name: AssemblyNamespace(compilation.Assembly), - Identity: compilation.Assembly.Identity.ToString(), - SharedContexts: UsesSharedContexts(compilation) + var environment = EnvironmentGenerator + .Declarations(context) + .Select( + (types, _) => + ( + HasDeclarations: types.Length != 0, + Registrations: EnvironmentGenerator.RegistrationCode(types) + ) + ); + var extensionNamespace = context + .CompilationProvider.Select( + (compilation, _) => + ( + Name: AssemblyNamespace(compilation.Assembly), + Identity: compilation.Assembly.Identity.ToString(), + SharedContexts: UsesSharedContexts(compilation) + ) ) - ).Combine(environment).Select((input, _) => ( - input.Left.Name, - input.Left.Identity, - input.Left.SharedContexts, - HasEnvironment: input.Right.HasDeclarations, - EnvironmentRegistrations: input.Right.Registrations - )); - + .Combine(environment) + .Select( + (input, _) => + ( + input.Left.Name, + input.Left.Identity, + input.Left.SharedContexts, + HasEnvironment: input.Right.HasDeclarations, + EnvironmentRegistrations: input.Right.Registrations + ) + ); + var referencedAssemblies = context.CompilationProvider.Select(DiscoverAssemblies); - var namespaceDeclarations = context.CompilationProvider - .Combine(referencedAssemblies) + var namespaceDeclarations = context + .CompilationProvider.Combine(referencedAssemblies) .Combine(tableDecls) - .SelectMany((input, ct) => new[] - { - DiagReporter.With(Location.None, diag => NamespaceDeclaration.Parse( - input.Left.Left, - input.Left.Right, - input.Right.SelectMany(t => t.TableAccessors.Select(a => a.Name)), - diag, - ct - )) - }) + .SelectMany( + (input, ct) => + new[] + { + DiagReporter.With( + Location.None, + diag => + NamespaceDeclaration.Parse( + input.Left.Left, + input.Left.Right, + input.Right.SelectMany(t => + t.TableAccessors.Select(a => a.Name) + ), + diag, + ct + ) + ), + } + ) .ReportDiagnostics(context) .WithTrackingName("SpacetimeDB.Namespace.Parse") .Collect(); @@ -2755,14 +2885,33 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Register the generated source code with the compilation context as part of module publishing // Once the compilation is complete, the generated code will be used to create tables and reducers in the database context.RegisterSourceOutput( - moduleOutputInputs.Combine(extensionNamespace).Combine(referencedAssemblies) + moduleOutputInputs + .Combine(extensionNamespace) + .Combine(referencedAssemblies) .Combine(namespaceDeclarations), (context, input) => { - var (((inputs, (extensionNamespaceName, identity, sharedContexts, hasEnvironment, environmentRegistrations)), assemblies), mounts) = input; + var ( + ( + ( + inputs, + ( + extensionNamespaceName, + identity, + sharedContexts, + hasEnvironment, + environmentRegistrations + ) + ), + assemblies + ), + mounts + ) = input; var handlesNamespace = sharedContexts - ? extensionNamespaceName : "SpacetimeDB.Internal"; - var mountByIdentity = mounts.SelectMany(m => m) + ? extensionNamespaceName + : "SpacetimeDB.Internal"; + var mountByIdentity = mounts + .SelectMany(m => m) .ToDictionary(m => m.AssemblyIdentity, StringComparer.Ordinal); bool IsChild(AssemblyDeclaration assembly) => mountByIdentity.TryGetValue(assembly.Identity, out var mount) @@ -2771,23 +2920,40 @@ bool IsChild(AssemblyDeclaration assembly) => var mountedAssemblies = assemblies.Where(IsChild).ToArray(); var registrationOrder = publicScopeAssemblies.Concat(mountedAssemblies).ToArray(); foreach (var assembly in assemblies.Where(a => a.DeclaresMounts)) - context.ReportDiagnostic(ErrorDescriptor.DependencyNamespaceMounts.ToDiag(assembly.Identity)); - foreach (var assembly in mountedAssemblies.Where(a => a.RootOnlyDeclarations.Length != 0)) - context.ReportDiagnostic(ErrorDescriptor.MountedRootOnlyDeclarations.ToDiag( - (assembly.Identity, mountByIdentity[assembly.Identity].Accessor, assembly.RootOnlyDeclarations))); + context.ReportDiagnostic( + ErrorDescriptor.DependencyNamespaceMounts.ToDiag(assembly.Identity) + ); + foreach ( + var assembly in mountedAssemblies.Where(a => a.RootOnlyDeclarations.Length != 0) + ) + context.ReportDiagnostic( + ErrorDescriptor.MountedRootOnlyDeclarations.ToDiag( + ( + assembly.Identity, + mountByIdentity[assembly.Identity].Accessor, + assembly.RootOnlyDeclarations + ) + ) + ); string GenerateDispatchRouting(string category, string arguments, string unknownId) { // Match Main's registration order; each category has its own local IDs. - var descriptors = new[] { $"global::{extensionNamespaceName}.AssemblyDescriptor" } - .Concat(registrationOrder.Select(assembly => assembly.DescriptorTypeName)); - var routes = descriptors.Select(descriptor => $$""" + var descriptors = new[] + { + $"global::{extensionNamespaceName}.AssemblyDescriptor", + }.Concat(registrationOrder.Select(assembly => assembly.DescriptorTypeName)); + var routes = descriptors.Select(descriptor => + $$""" if ((uint)localId < (uint){{descriptor}}.{{category}}Count) return {{descriptor}}.CallLocal{{category}}(localId, {{arguments}}); localId -= {{descriptor}}.{{category}}Count; - """); + """ + ); return $"if (id < 0) {{ {unknownId} }}\nvar localId = id;\n" - + string.Join("\n", routes) + "\n" + unknownId; + + string.Join("\n", routes) + + "\n" + + unknownId; } var ( @@ -2806,14 +2972,27 @@ string GenerateDispatchRouting(string category, string arguments, string unknown if (sharedContexts) { - var generatedNames = new GeneratedNames((scope, name, first, second) => - context.ReportDiagnostic(ErrorDescriptor.GeneratedNameCollision.ToDiag( - (Location.None, scope, name, first, second)))); + var generatedNames = new GeneratedNames( + (scope, name, first, second) => + context.ReportDiagnostic( + ErrorDescriptor.GeneratedNameCollision.ToDiag( + (Location.None, scope, name, first, second) + ) + ) + ); foreach (var table in tableAccessors) { var owner = $"table '{table.TableAccessorName}' on '{table.TableName}'"; - generatedNames.Add(extensionNamespaceName, EscapeIdentifier(table.TableAccessorName + "Cols"), owner); - generatedNames.Add(extensionNamespaceName, EscapeIdentifier(table.TableAccessorName + "IxCols"), owner); + generatedNames.Add( + extensionNamespaceName, + EscapeIdentifier(table.TableAccessorName + "Cols"), + owner + ); + generatedNames.Add( + extensionNamespaceName, + EscapeIdentifier(table.TableAccessorName + "IxCols"), + owner + ); } } @@ -2828,8 +3007,11 @@ void Add(string name, string owner, string declaration) if (used.TryGetValue(name, out var previous)) { if (container == "Tables") - context.ReportDiagnostic(ErrorDescriptor.NamespaceAccessorCollision.ToDiag( - (name, previous, owner))); + context.ReportDiagnostic( + ErrorDescriptor.NamespaceAccessorCollision.ToDiag( + (name, previous, owner) + ) + ); return; } used.Add(name, owner); @@ -2839,8 +3021,11 @@ void Add(string name, string owner, string declaration) { if (mountByIdentity.TryGetValue(assembly.Identity, out var mount)) { - Add(mount.Accessor, assembly.Identity, - $"public {assembly.DescriptorTypeName}.{container} {mount.AccessorIdentifier} => new();"); + Add( + mount.Accessor, + assembly.Identity, + $"public {assembly.DescriptorTypeName}.{container} {mount.AccessorIdentifier} => new();" + ); } else { @@ -2852,8 +3037,11 @@ void Add(string name, string owner, string declaration) }; var invocation = container == "Queries" ? "()" : ""; foreach (var table in accessors) - Add(table.Name, assembly.Identity, - $"public {table.TypeName} {EscapeIdentifier(table.Name)}{invocation} => new {assembly.DescriptorTypeName}.{container}().{EscapeIdentifier(table.Name)}{invocation};"); + Add( + table.Name, + assembly.Identity, + $"public {table.TypeName} {EscapeIdentifier(table.Name)}{invocation} => new {assembly.DescriptorTypeName}.{container}().{EscapeIdentifier(table.Name)}{invocation};" + ); } } return string.Join("\n", members); @@ -2865,19 +3053,33 @@ void Add(string name, string owner, string declaration) var compositionRegistration = new List { "global::SpacetimeDB.Internal.Module.InstallNamespaces(new global::SpacetimeDB.Internal.NamespaceRegistry(" - + SymbolDisplay.FormatLiteral(identity, true) + ", new global::System.Collections.Generic.KeyValuePair[] {" - + string.Join(",", mountByIdentity.Values.Select(m => - $"new({SymbolDisplay.FormatLiteral(m.AssemblyIdentity, true)}, {SymbolDisplay.FormatLiteral(m.Accessor, true)})")) + "}));", - $"global::{extensionNamespaceName}.AssemblyDescriptor.Register(global::SpacetimeDB.Internal.Module.RootBuilder);" + + SymbolDisplay.FormatLiteral(identity, true) + + ", new global::System.Collections.Generic.KeyValuePair[] {" + + string.Join( + ",", + mountByIdentity.Values.Select(m => + $"new({SymbolDisplay.FormatLiteral(m.AssemblyIdentity, true)}, {SymbolDisplay.FormatLiteral(m.Accessor, true)})" + ) + ) + + "}));", + $"global::{extensionNamespaceName}.AssemblyDescriptor.Register(global::SpacetimeDB.Internal.Module.RootBuilder);", }; foreach (var assembly in publicScopeAssemblies) - compositionRegistration.Add($"{assembly.DescriptorTypeName}.Register(global::SpacetimeDB.Internal.Module.RootBuilder);"); + compositionRegistration.Add( + $"{assembly.DescriptorTypeName}.Register(global::SpacetimeDB.Internal.Module.RootBuilder);" + ); for (var i = 0; i < mountedAssemblies.Length; i++) { var assembly = mountedAssemblies[i]; - compositionRegistration.Add($"var child{i} = new global::SpacetimeDB.Internal.ModuleBuilder();"); - compositionRegistration.Add($"{assembly.DescriptorTypeName}.Register(child{i}, global::SpacetimeDB.Internal.Module.RootBuilder);"); - compositionRegistration.Add($"global::SpacetimeDB.Internal.Module.RootBuilder.RegisterSubmodule({SymbolDisplay.FormatLiteral(mountByIdentity[assembly.Identity].Accessor, true)}, child{i});"); + compositionRegistration.Add( + $"var child{i} = new global::SpacetimeDB.Internal.ModuleBuilder();" + ); + compositionRegistration.Add( + $"{assembly.DescriptorTypeName}.Register(child{i}, global::SpacetimeDB.Internal.Module.RootBuilder);" + ); + compositionRegistration.Add( + $"global::SpacetimeDB.Internal.Module.RootBuilder.RegisterSubmodule({SymbolDisplay.FormatLiteral(mountByIdentity[assembly.Identity].Accessor, true)}, child{i});" + ); } if (settings.Array.Length > 1) @@ -2969,7 +3171,9 @@ void Add(string name, string owner, string declaration) ); var queryBuilderExtensionMembers = string.Join( "\n", - tableDecls.Array.SelectMany(t => t.GenerateQueryBuilderMembers(useExtensions: true)) + tableDecls.Array.SelectMany(t => + t.GenerateQueryBuilderMembers(useExtensions: true) + ) ); if (string.IsNullOrWhiteSpace(queryBuilderMembers)) { diff --git a/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs b/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs index 406fc0b3ef6..d5152403137 100644 --- a/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs +++ b/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs @@ -129,7 +129,9 @@ void CheckDuplicate(Dictionary seen, string key, string m if (tables.Contains(accessor)) Error($"Namespace accessor '{accessor}' conflicts with a root table accessor."); if (accessor is "GetType" or "ToString" or "Equals" or "GetHashCode") - Error($"Namespace accessor '{accessor}' conflicts with an existing context database/query receiver member."); + Error( + $"Namespace accessor '{accessor}' conflicts with an existing context database/query receiver member." + ); if (valid) result.Add(new(identity, accessor)); diff --git a/crates/bindings-csharp/Runtime/Attrs.cs b/crates/bindings-csharp/Runtime/Attrs.cs index af1edcb5bc3..e1b2ad9c340 100644 --- a/crates/bindings-csharp/Runtime/Attrs.cs +++ b/crates/bindings-csharp/Runtime/Attrs.cs @@ -250,7 +250,7 @@ public sealed class HttpHandlerAttribute() : Attribute { } [AttributeUsage(AttributeTargets.Method, Inherited = false)] public sealed class HttpRouterAttribute() : Attribute { } - + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)] public sealed class ModuleDescriptorAttribute(Type descriptorType) : Attribute { diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index c3dcad6ad1a..a9a5794b86b 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -56,12 +56,16 @@ public static void InstallNamespaces(NamespaceRegistry registry) } public static string ResolveName(string assemblyIdentity, string localName) => - (namespaces ?? throw new InvalidOperationException("Module namespaces have not been installed.")) - .Resolve(assemblyIdentity, localName); + ( + namespaces + ?? throw new InvalidOperationException("Module namespaces have not been installed.") + ).Resolve(assemblyIdentity, localName); public static SqlTableName ResolveSqlName(string assemblyIdentity, string localName) => - (namespaces ?? throw new InvalidOperationException("Module namespaces have not been installed.")) - .ResolveSqlName(assemblyIdentity, localName); + ( + namespaces + ?? throw new InvalidOperationException("Module namespaces have not been installed.") + ).ResolveSqlName(assemblyIdentity, localName); private static Func< Identity, @@ -71,26 +75,29 @@ private static Func< IReducerContext >? newReducerContext = #if NET10_0_OR_GREATER - (identity, connectionId, random, time) => - new SpacetimeDB.ReducerContext(identity, connectionId, random, time); + (identity, connectionId, random, time) => + new SpacetimeDB.ReducerContext(identity, connectionId, random, time); #else null; #endif private static Func? newViewContext = #if NET10_0_OR_GREATER - identity => new ViewContext(identity, new LocalReadOnly()); + identity => new ViewContext(identity, new LocalReadOnly()); #else null; #endif private static Func? newAnonymousViewContext = #if NET10_0_OR_GREATER - () => new AnonymousViewContext(new LocalReadOnly()); + () => new AnonymousViewContext(new LocalReadOnly()); #else null; #endif private static Func? newHandlerContext = #if NET10_0_OR_GREATER - (random, time) => new HandlerContext(random, time); + ( + random, + time + ) => new HandlerContext(random, time); #else null; #endif @@ -103,8 +110,8 @@ private static Func< IProcedureContext >? newProcedureContext = #if NET10_0_OR_GREATER - (identity, connectionId, random, time) => - new ProcedureContext(identity, connectionId, random, time); + (identity, connectionId, random, time) => + new ProcedureContext(identity, connectionId, random, time); #else null; #endif @@ -158,28 +165,23 @@ public AlgebraicType.Ref RegisterType(Func } public static void RegisterReducer() - where R : IReducer, new() => - RootBuilder.RegisterReducer(); + where R : IReducer, new() => RootBuilder.RegisterReducer(); public static void RegisterProcedure

() - where P : IProcedure, new() => - RootBuilder.RegisterProcedure

(); + where P : IProcedure, new() => RootBuilder.RegisterProcedure

(); public static void RegisterHttpHandler() - where H : IHttpHandler, new() => - RootBuilder.RegisterHttpHandler(); + where H : IHttpHandler, new() => RootBuilder.RegisterHttpHandler(); public static void RegisterHttpRouter(SpacetimeDB.Router router) => RootBuilder.RegisterHttpRouter(router); public static void RegisterTable() where T : IStructuralReadWrite, new() - where View : ITableView, new() => - RootBuilder.RegisterTable(); + where View : ITableView, new() => RootBuilder.RegisterTable(); public static void RegisterView() - where TDispatcher : IView, new() => - RootBuilder.RegisterView(); + where TDispatcher : IView, new() => RootBuilder.RegisterView(); public static void RegisterAnonymousView() where TDispatcher : IAnonymousView, new() => @@ -422,6 +424,4 @@ public partial class Local /// On .NET 10 the generator provides assembly-scoped extension properties. /// On .NET 8 generated modules declare their own type with table accessors. ///

-public sealed partial class LocalReadOnly -{ -} +public sealed partial class LocalReadOnly { } diff --git a/crates/bindings-csharp/Runtime/ModuleContexts.cs b/crates/bindings-csharp/Runtime/ModuleContexts.cs index 8bbde15ab77..aaa8649d997 100644 --- a/crates/bindings-csharp/Runtime/ModuleContexts.cs +++ b/crates/bindings-csharp/Runtime/ModuleContexts.cs @@ -8,22 +8,32 @@ namespace SpacetimeDB; public sealed class Local : LocalBase { } -public sealed record ReducerContext : DbContext, Internal.IReducerContext { +public sealed record ReducerContext : DbContext, Internal.IReducerContext +{ public DatabaseEnvironment Env => default; public readonly Identity Sender; public readonly ConnectionId? ConnectionId; public readonly Random Rng; public readonly Timestamp Timestamp; public readonly AuthCtx SenderAuth; + // **Note:** must be 0..=u32::MAX internal int CounterUuid; public Identity DatabaseIdentity => Internal.IReducerContext.GetDatabaseIdentity(); + // We keep this property for compatibility with existing module code. - [global::System.Obsolete("ReducerContext.Identity is deprecated. Use DatabaseIdentity instead.")] + [global::System.Obsolete( + "ReducerContext.Identity is deprecated. Use DatabaseIdentity instead." + )] public Identity Identity => DatabaseIdentity; - internal ReducerContext(Identity identity, ConnectionId? connectionId, Random random, - Timestamp time, AuthCtx? senderAuth = null) + internal ReducerContext( + Identity identity, + ConnectionId? connectionId, + Random random, + Timestamp time, + AuthCtx? senderAuth = null + ) { Sender = identity; ConnectionId = connectionId; @@ -32,6 +42,7 @@ internal ReducerContext(Identity identity, ConnectionId? connectionId, Random ra SenderAuth = senderAuth ?? AuthCtx.BuildFromSystemTables(connectionId, identity); CounterUuid = 0; } + /// /// Create a new random `v4` using the built-in RNG. /// @@ -82,15 +93,23 @@ public Uuid NewUuidV7() public readonly struct QueryBuilder { } -public sealed partial class ProcedureContext : global::SpacetimeDB.ProcedureContextBase { +public sealed partial class ProcedureContext : global::SpacetimeDB.ProcedureContextBase +{ private readonly Local _db = new(); - internal ProcedureContext(Identity identity, ConnectionId? connectionId, Random random, Timestamp time) - : base(identity, connectionId, random, time) {} + internal ProcedureContext( + Identity identity, + ConnectionId? connectionId, + Random random, + Timestamp time + ) + : base(identity, connectionId, random, time) { } protected internal override global::SpacetimeDB.LocalBase CreateLocal() => _db; - protected override global::SpacetimeDB.ProcedureTxContextBase CreateTxContext(Internal.TxContext inner) => - _cached ??= new ProcedureTxContext(inner); + + protected override global::SpacetimeDB.ProcedureTxContextBase CreateTxContext( + Internal.TxContext inner + ) => _cached ??= new ProcedureTxContext(inner); private ProcedureTxContext? _cached; @@ -100,9 +119,9 @@ public TResult WithTx(Func body) => base.WithTx(tx => body((ProcedureTxContext)tx)); public TxOutcome TryWithTx( - Func> body) - where TError : Exception => - base.TryWithTx(tx => body((ProcedureTxContext)tx)); + Func> body + ) + where TError : Exception => base.TryWithTx(tx => body((ProcedureTxContext)tx)); /// /// Create a new random `v4` using the built-in RNG. @@ -152,15 +171,18 @@ public Uuid NewUuidV7() } } -public sealed partial class HandlerContext : global::SpacetimeDB.HandlerContextBase { +public sealed partial class HandlerContext : global::SpacetimeDB.HandlerContextBase +{ private readonly Local _db = new(); internal HandlerContext(Random random, Timestamp time) - : base(random, time) {} + : base(random, time) { } protected override global::SpacetimeDB.LocalBase CreateLocal() => _db; - protected override global::SpacetimeDB.HandlerTxContextBase CreateTxContext(Internal.TxContext inner) => - _cached ??= new HandlerTxContext(inner); + + protected override global::SpacetimeDB.HandlerTxContextBase CreateTxContext( + Internal.TxContext inner + ) => _cached ??= new HandlerTxContext(inner); private HandlerTxContext? _cached; @@ -170,9 +192,9 @@ public TResult WithTx(Func body) => [Experimental("STDB_UNSTABLE")] public TxOutcome TryWithTx( - Func> body) - where TError : Exception => - base.TryWithTx(tx => body((HandlerTxContext)tx)); + Func> body + ) + where TError : Exception => base.TryWithTx(tx => body((HandlerTxContext)tx)); public Uuid NewUuidV4() { @@ -189,15 +211,19 @@ public Uuid NewUuidV7() } } -public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase { - internal ProcedureTxContext(Internal.TxContext inner) : base(inner) {} +public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase +{ + internal ProcedureTxContext(Internal.TxContext inner) + : base(inner) { } public new Local Db => (Local)base.Db; } [Experimental("STDB_UNSTABLE")] -public sealed class HandlerTxContext : global::SpacetimeDB.HandlerTxContextBase { - internal HandlerTxContext(Internal.TxContext inner) : base(inner) {} +public sealed class HandlerTxContext : global::SpacetimeDB.HandlerTxContextBase +{ + internal HandlerTxContext(Internal.TxContext inner) + : base(inner) { } public new Local Db => (Local)base.Db; } @@ -216,7 +242,9 @@ internal ViewContext(Identity sender, Internal.LocalReadOnly db) } } -public sealed record AnonymousViewContext : DbContext, Internal.IAnonymousViewContext +public sealed record AnonymousViewContext + : DbContext, + Internal.IAnonymousViewContext { public DatabaseEnvironment Env => default; public QueryBuilder From => default; From 5666a459099ab582099705f6e9ce8759e1b335da Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 12:35:09 -0500 Subject: [PATCH 38/49] Run csharpier --- crates/bindings-csharp/Codegen/Diag.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bindings-csharp/Codegen/Diag.cs b/crates/bindings-csharp/Codegen/Diag.cs index 4bcd0ba05f8..8f1e7498a94 100644 --- a/crates/bindings-csharp/Codegen/Diag.cs +++ b/crates/bindings-csharp/Codegen/Diag.cs @@ -365,7 +365,7 @@ string type public static readonly ErrorDescriptor<( ISymbol symbol, string message - )> InvalidEnvironmentDeclaration = + )> InvalidEnvironmentDeclaration = new(group, "Invalid environment declaration", ctx => $"{ctx.message}", ctx => ctx.symbol); public static readonly ErrorDescriptor<( From d108e012fed9cb2474afa3051a21832b11d16bf7 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 12:39:28 -0500 Subject: [PATCH 39/49] Minor cleanup --- crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs b/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs index e7260e94379..952c602f545 100644 --- a/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs +++ b/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs @@ -1,7 +1,6 @@ namespace SpacetimeDB; using System; -using System.Collections.Generic; using System.Globalization; /// A table identifier with a separately quoted optional namespace and local name. @@ -18,12 +17,7 @@ public SqlTableName(string localName) public SqlTableName(string @namespace, string localName) { - if (@namespace is null) - { - throw new ArgumentNullException(nameof(@namespace)); - } - - Namespace = @namespace; + Namespace = @namespace ?? throw new ArgumentNullException(nameof(@namespace)); LocalName = localName; } From 6bde0c7ab0cc135f647d85ca6b0be8d8269de579 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 13:12:47 -0500 Subject: [PATCH 40/49] Clean up --- .../Codegen.Tests/EnvironmentTests.cs | 2 +- crates/bindings-csharp/Codegen.Tests/Tests.cs | 5 + crates/bindings-csharp/Codegen/Environment.cs | 8 + .../bindings-csharp/Codegen/GeneratedNames.cs | 4 + crates/bindings-csharp/Codegen/Module.cs | 11 ++ .../Codegen/NamespaceDeclaration.cs | 155 ++++++++++++++---- .../Runtime/Internal/NamespaceRegistry.cs | 5 + modules/namespace-environment-test-cs/Lib.cs | 12 ++ .../libraries/AuthLib/Lib.cs | 5 + .../libraries/PublicLib/Lib.cs | 3 + modules/namespace-test-cs/Lib.cs | 19 +++ .../libraries/AuditLib/Scheduled.cs | 12 ++ .../libraries/AuthLib/Lib.cs | 3 + .../libraries/AuthLib/Scheduled.cs | 12 ++ .../regression-tests/namespaces/Program.cs | 22 +++ .../namespaces/RootRlsTests.cs | 10 ++ sdks/csharp/src/Table.cs | 6 +- 17 files changed, 260 insertions(+), 34 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs b/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs index 25dcd1f66de..a609a4db9c9 100644 --- a/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs +++ b/crates/bindings-csharp/Codegen.Tests/EnvironmentTests.cs @@ -162,7 +162,7 @@ public static void InvalidDeclarationsAreCompileErrors(string field) Assert.Contains( result.Diagnostics, diagnostic => - diagnostic.Id == "STDB0044" && diagnostic.Severity == DiagnosticSeverity.Error + diagnostic.Id == "STDB0039" && diagnostic.Severity == DiagnosticSeverity.Error ); } diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index cdcf7df36a0..2804f3c8cd2 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -611,10 +611,13 @@ MethodDeclarationSyntax Method(CSharpCompilation compilation, string name) => ); var rootSource = rootHasTable ? Table("Root") : ""; if (mounted) + { rootSource = "[assembly: SpacetimeDB.Namespace(typeof(Alpha.Sentinel), Accessor = \"Auth\")]\n" + "[assembly: SpacetimeDB.Namespace(typeof(Beta.Sentinel), Accessor = \"class\")]\n" + rootSource; + } + var root = Generate(Create("Root", rootSource, beta, utility, shared, alpha)); var reordered = Generate(Create("Root", rootSource, alpha, shared, utility, beta)); @@ -648,7 +651,9 @@ .. Method(compilation, "Initialize") Assert.Equal(expected, Calls(reordered)); if (rootHasTable || mounted) + { return; + } // An unrelated utility alone must not cause an otherwise empty module to register. var plainUtility = Emit(Create("PlainUtility", "public class PlainUtility { }")); diff --git a/crates/bindings-csharp/Codegen/Environment.cs b/crates/bindings-csharp/Codegen/Environment.cs index b8dce6ee34b..782fe30d69c 100644 --- a/crates/bindings-csharp/Codegen/Environment.cs +++ b/crates/bindings-csharp/Codegen/Environment.cs @@ -60,7 +60,9 @@ Action Report .Where(field => !field.IsImplicitlyDeclared) .ToArray(); if (fields.Length > 256 && types.Length != 0) + { Report(types[0], "An environment schema may declare at most 256 variables."); + } var keys = new HashSet(StringComparer.Ordinal); var properties = new List(); @@ -141,11 +143,17 @@ Action Report or "GetType" or "MemberwiseClone" ) + { continue; + } + var read = $"{(sharedContexts ? "env." : "")}Get({Literal(name)})"; if (!optional) + { read += " ?? throw new global::System.InvalidOperationException(\"Required environment value is absent\")"; + } + properties.Add($"public string{(optional ? "?" : "")} @{name} => {read};"); } return (properties, registrations); diff --git a/crates/bindings-csharp/Codegen/GeneratedNames.cs b/crates/bindings-csharp/Codegen/GeneratedNames.cs index 5ae6c609592..cede1fc020c 100644 --- a/crates/bindings-csharp/Codegen/GeneratedNames.cs +++ b/crates/bindings-csharp/Codegen/GeneratedNames.cs @@ -19,8 +19,12 @@ internal void Add(string scope, string identifier, string contributor) var name = SyntaxFactory.ParseToken(identifier).ValueText; var key = (scope, name); if (declarations.TryGetValue(key, out var previous)) + { report(scope, name, previous, contributor); + } else + { declarations.Add(key, contributor); + } } } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index c62d7ccffbf..48b29c4c682 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -595,7 +595,9 @@ public TableDeclaration(GeneratorAttributeSyntaxContext context, DiagReporter di .ToImmutableArray() ); if (sharedContexts) + { ValidateGeneratedNames(diag, typeSyntax.GetLocation()); + } } private void ValidateGeneratedNames(DiagReporter diag, Location location) @@ -663,10 +665,14 @@ var constraint in GetConstraints(table, ColumnAttrs.Unique) foreach (var container in new[] { "Tables", "ReadOnlyTables", "Queries" }) if (table.Name == container) + { names.Add(container, container, "enclosing descriptor container"); + } + foreach (var container in new[] { "Tables", "ReadOnlyTables", "Queries" }) names.Add(container, table.Identifier, owner); if (table.Name is "GetType" or "ToString" or "Equals" or "GetHashCode") + { diag.Report( ErrorDescriptor.GeneratedNameCollision, ( @@ -677,6 +683,8 @@ var constraint in GetConstraints(table, ColumnAttrs.Unique) owner ) ); + } + var cols = table.Identifier + "Cols"; names.Add(cols, cols, "enclosing query columns type"); foreach (var column in Members) @@ -3007,11 +3015,14 @@ void Add(string name, string owner, string declaration) if (used.TryGetValue(name, out var previous)) { if (container == "Tables") + { context.ReportDiagnostic( ErrorDescriptor.NamespaceAccessorCollision.ToDiag( (name, previous, owner) ) ); + } + return; } used.Add(name, owner); diff --git a/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs b/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs index d5152403137..bad9d6b66ee 100644 --- a/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs +++ b/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs @@ -6,7 +6,7 @@ namespace SpacetimeDB.Codegen; using Microsoft.CodeAnalysis.CSharp; using static Utils; -record NamespaceDeclaration(string AssemblyIdentity, string Accessor) +internal record NamespaceDeclaration(string AssemblyIdentity, string Accessor) { public string AccessorIdentifier => EscapeIdentifier(Accessor); @@ -21,11 +21,18 @@ CancellationToken cancellationToken var attributeType = compilation.GetTypeByMetadataName("SpacetimeDB.NamespaceAttribute"); var result = ImmutableArray.CreateBuilder(); if (attributeType is null) - return new(result.ToImmutable()); + { + return new EquatableArray(result.ToImmutable()); + } + var identities = new Dictionary(StringComparer.Ordinal); var accessors = new Dictionary(StringComparer.OrdinalIgnoreCase); var tables = new HashSet(tableAccessors, StringComparer.Ordinal); - var supported = compilation.SyntaxTrees.Any(tree => + var assemblyIdentities = new HashSet( + assemblies.Select(static assembly => assembly.Identity), + StringComparer.Ordinal + ); + var supported = compilation.SyntaxTrees.Any(static tree => tree.Options is CSharpParseOptions options && options.PreprocessorSymbolNames.Contains("NET10_0_OR_GREATER") // Use the numeric value to keep the analyzer compatible with Roslyn 4.3. @@ -36,24 +43,32 @@ tree.Options is CSharpParseOptions options { cancellationToken.ThrowIfCancellationRequested(); if (!SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, attributeType)) + { continue; + } var valid = true; - void Error(string message) + if (!supported) { - valid = false; - diag.Report(ErrorDescriptor.InvalidNamespace, (attribute, message)); + ReportError( + diag, + attribute, + ref valid, + "Namespace mounts require .NET 10 and C# 14." + ); } - if (!supported) - Error("Namespace mounts require .NET 10 and C# 14."); - if ( attribute.ConstructorArguments.Length != 1 || attribute.ConstructorArguments[0].Value is not INamedTypeSymbol marker ) { - Error("A namespace mount requires a marker type declared in a module assembly."); + ReportError( + diag, + attribute, + ref valid, + "A namespace mount requires a marker type declared in a module assembly." + ); continue; } @@ -64,12 +79,21 @@ void Error(string message) compilation.Assembly ) ) - Error("The root assembly cannot mount itself."); - else if (supported && !assemblies.Any(a => a.Identity == identity)) - Error($"Assembly '{identity}' has no discovered module descriptor."); + { + ReportError(diag, attribute, ref valid, "The root assembly cannot mount itself."); + } + else if (supported && !assemblyIdentities.Contains(identity)) + { + ReportError( + diag, + attribute, + ref valid, + $"Assembly '{identity}' has no discovered module descriptor." + ); + } var accessor = - attribute.NamedArguments.FirstOrDefault(a => a.Key == "Accessor").Value.Value + attribute.NamedArguments.FirstOrDefault(static a => a.Key == "Accessor").Value.Value as string ?? ""; // Keywords are stored unescaped and escaped only when rendering C#. @@ -82,60 +106,127 @@ as string ) || SyntaxFactory.ParseToken(EscapeIdentifier(accessor)).ValueText != accessor ) - Error("Accessor must be a nonempty C# identifier (use keyword names without '@')."); + { + ReportError( + diag, + attribute, + ref valid, + "Accessor must be a nonempty C# identifier (use keyword names without '@')." + ); + } // The accessor is also the database namespace, so both sets of rules apply. // The host remains authoritative for full Unicode identifier validation. if ( accessor.Length == 0 || !(char.IsLetter(accessor[0]) || accessor[0] == '_') - || accessor.Any(c => !(char.IsLetterOrDigit(c) || c == '_')) + || accessor.Any(static c => !(char.IsLetterOrDigit(c) || c == '_')) || !accessor.IsNormalized(NormalizationForm.FormC) ) - Error( + { + ReportError( + diag, + attribute, + ref valid, "Accessor must also be a nonempty database identifier: letters, digits or underscores, starting with a letter or underscore." ); + } + if (Encoding.UTF8.GetByteCount(accessor) > 63) - Error("Namespace names cannot exceed 63 UTF-8 bytes (the current host limit)."); + { + ReportError( + diag, + attribute, + ref valid, + "Namespace names cannot exceed 63 UTF-8 bytes (the current host limit)." + ); + } + if ( accessor.Equals("st", StringComparison.OrdinalIgnoreCase) || accessor.Equals("spacetimedb", StringComparison.OrdinalIgnoreCase) || accessor.StartsWith("pg_", StringComparison.OrdinalIgnoreCase) ) - Error($"Namespace '{accessor}' is reserved."); - - void CheckDuplicate(Dictionary seen, string key, string message) { - if (seen.TryGetValue(key, out var previous)) - { - Error(message); - diag.Report(ErrorDescriptor.InvalidNamespace, (previous, message)); - } - else - seen.Add(key, attribute); + ReportError(diag, attribute, ref valid, $"Namespace '{accessor}' is reserved."); } CheckDuplicate( + diag, + attribute, + ref valid, identities, identity, $"Assembly '{identity}' may only be mounted once." ); if (accessor.Length > 0) + { CheckDuplicate( + diag, + attribute, + ref valid, accessors, accessor, $"Namespace accessor '{accessor}' is declared more than once (case-insensitive)." ); + } + if (tables.Contains(accessor)) - Error($"Namespace accessor '{accessor}' conflicts with a root table accessor."); + { + ReportError( + diag, + attribute, + ref valid, + $"Namespace accessor '{accessor}' conflicts with a root table accessor." + ); + } + if (accessor is "GetType" or "ToString" or "Equals" or "GetHashCode") - Error( + { + ReportError( + diag, + attribute, + ref valid, $"Namespace accessor '{accessor}' conflicts with an existing context database/query receiver member." ); + } if (valid) - result.Add(new(identity, accessor)); + { + result.Add(new NamespaceDeclaration(identity, accessor)); + } + } + return new EquatableArray(result.ToImmutable()); + } + + private static void ReportError( + DiagReporter diag, + AttributeData attribute, + ref bool valid, + string message + ) + { + valid = false; + diag.Report(ErrorDescriptor.InvalidNamespace, (attribute, message)); + } + + private static void CheckDuplicate( + DiagReporter diag, + AttributeData attribute, + ref bool valid, + Dictionary seen, + string key, + string message + ) + { + if (seen.TryGetValue(key, out var previous)) + { + ReportError(diag, attribute, ref valid, message); + diag.Report(ErrorDescriptor.InvalidNamespace, (previous, message)); + } + else + { + seen.Add(key, attribute); } - return new(result.ToImmutable()); } } diff --git a/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs b/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs index 4244b9bc0fa..f3aa2019fc0 100644 --- a/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs +++ b/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs @@ -10,12 +10,17 @@ public NamespaceRegistry(string rootIdentity, IEnumerable { if (tx.Env.NAMESPACE_TEST != value) + { throw new Exception("Root transaction environment mismatch"); + } + return value ?? "unset"; }); } @@ -36,7 +45,10 @@ public static Router Routes() => public static void ExpectEnvironment(ReducerContext ctx, string? expected) { if (ctx.Env.NAMESPACE_TEST != expected) + { throw new Exception("Root environment mismatch"); + } + AuthLib.Functions.ExpectEnvironment(ctx, expected); } diff --git a/modules/namespace-environment-test-cs/libraries/AuthLib/Lib.cs b/modules/namespace-environment-test-cs/libraries/AuthLib/Lib.cs index 69555d4994c..868ca30fa51 100644 --- a/modules/namespace-environment-test-cs/libraries/AuthLib/Lib.cs +++ b/modules/namespace-environment-test-cs/libraries/AuthLib/Lib.cs @@ -24,7 +24,9 @@ public static Router Routes() => public static void ExpectEnvironment(ReducerContext ctx, string? expected) { if (ctx.Env.Get("NAMESPACE_TEST") != expected) + { throw new Exception("Library environment mismatch"); + } } [Procedure] @@ -36,7 +38,10 @@ public static HttpResponse EnvironmentHandler(HandlerContext ctx, HttpRequest re { var value = ctx.Env.Get("NAMESPACE_TEST"); if (ctx.WithTx(tx => tx.Env.Get("NAMESPACE_TEST")) != value) + { throw new Exception("Handler transaction environment mismatch"); + } + return new(200, HttpVersion.Http11, [], HttpBody.FromString(value ?? "unset")); } diff --git a/modules/namespace-environment-test-cs/libraries/PublicLib/Lib.cs b/modules/namespace-environment-test-cs/libraries/PublicLib/Lib.cs index 40a7bfd1c2e..4e651699937 100644 --- a/modules/namespace-environment-test-cs/libraries/PublicLib/Lib.cs +++ b/modules/namespace-environment-test-cs/libraries/PublicLib/Lib.cs @@ -15,7 +15,10 @@ public static string ReadPublicEnvironment(ProcedureContext ctx) { var value = ctx.Env.PUBLIC_LIBRARY_TEST; if (ctx.WithTx(tx => tx.Env.PUBLIC_LIBRARY_TEST) != value) + { throw new Exception("Public library transaction environment mismatch"); + } + return value ?? "unset"; } } diff --git a/modules/namespace-test-cs/Lib.cs b/modules/namespace-test-cs/Lib.cs index a6736e71ca1..6e70ffd6ad8 100644 --- a/modules/namespace-test-cs/Lib.cs +++ b/modules/namespace-test-cs/Lib.cs @@ -56,9 +56,13 @@ public static void WriteProtectedRow(ReducerContext ctx, uint id, Identity owner Value = value, }; if (ctx.Db.MyAuth.ProtectedRow.Id.Find(id) is null) + { ctx.Db.MyAuth.ProtectedRow.Insert(row); + } else + { ctx.Db.MyAuth.ProtectedRow.Id.Update(row); + } } [Reducer] @@ -71,7 +75,10 @@ public static void Exercise(ReducerContext ctx) || ReferenceEquals(ctx.Db.User.Id, ctx.Db.MyAuth.User.Id) || ReferenceEquals(ctx.Db.MyAuth.User.Id, ctx.Db.@class.User.Id) ) + { throw new Exception("Index handles must be reused within, but not across, table scopes."); + } + ctx.Db.User.Insert(new User { Id = 2 }); AuthLib.Functions.Insert(ctx, 2); ctx.Db.MyAuth.User.Insert(new AuthLib.User { Id = 3, Score = 43 }); @@ -82,14 +89,23 @@ public static void Exercise(ReducerContext ctx) || ctx.Db.@class.User.Count != 1 || ctx.Db.ExtraRow.Count != 1 ) + { throw new Exception("Namespace counts are not isolated."); + } + var row = ctx.Db.MyAuth.User.Id.Find(2)!.Value; row.Score = 99; ctx.Db.MyAuth.User.Id.Update(row); if (ctx.Db.MyAuth.User.ByScore.Filter(99u).Single().Id != 2) + { throw new Exception("Mounted index lookup failed."); + } + if (!ctx.Db.MyAuth.User.Id.Delete(3) || ctx.Db.MyAuth.User.Count != 1) + { throw new Exception("Mounted unique deletion failed."); + } + Log.Info("namespace composition works"); } @@ -105,7 +121,10 @@ public static uint WriteAcrossNamespaces(ProcedureContext ctx, uint id, bool fai AuthLib.Functions.Insert(tx, id); tx.Db.@class.User.Insert(new AuditLib.User { Id = id, Message = "procedure" }); if (fail) + { throw new Exception("cross-namespace procedure rollback"); + } + return tx.Db.MyAuth.User.Id.Find(id)!.Value.Score; }); diff --git a/modules/namespace-test-cs/libraries/AuditLib/Scheduled.cs b/modules/namespace-test-cs/libraries/AuditLib/Scheduled.cs index a681356f59d..dac8bc2a193 100644 --- a/modules/namespace-test-cs/libraries/AuditLib/Scheduled.cs +++ b/modules/namespace-test-cs/libraries/AuditLib/Scheduled.cs @@ -108,9 +108,13 @@ public static void ReducerTick(ReducerContext ctx, ReducerJob job) ScheduledId = job.Id, }; if (previous is null) + { ctx.Db.ScheduleResult.Insert(result); + } else + { ctx.Db.ScheduleResult.JobId.Update(result); + } } [Procedure(Name = "run_procedure_job")] @@ -128,9 +132,14 @@ public static void ProcedureTick(ProcedureContext ctx, ProcedureJob job) ScheduledId = job.Id, }; if (previous is null) + { tx.Db.ScheduleResult.Insert(result); + } else + { tx.Db.ScheduleResult.JobId.Update(result); + } + return 0; }); } @@ -140,7 +149,10 @@ public static void CancelSchedules(ReducerContext ctx) { var repeat = ctx.Db.ScheduleResult.JobId.Find(5)!.Value; if (repeat.Executions < 2) + { throw new Exception("Repeating schedule has not run twice."); + } + ctx.Db.ReducerJob.Id.Delete(repeat.ScheduledId); ctx.Db.ScheduleResult.Insert( new ScheduleResult diff --git a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs index f24682c8730..080d2a57f3a 100644 --- a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs +++ b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs @@ -92,7 +92,10 @@ public static uint ReadScore(ProcedureContext ctx, uint id) => !ReferenceEquals(ctx.Db.User.Id, ctx.Db.User.Id) || !ReferenceEquals(ctx.Db.User.ByScore, ctx.Db.User.ByScore) ) + { throw new Exception("Read-only index handles must be reused."); + } + return ctx.Db.User.Id.Find(2); } diff --git a/modules/namespace-test-cs/libraries/AuthLib/Scheduled.cs b/modules/namespace-test-cs/libraries/AuthLib/Scheduled.cs index 9778673d889..a6521e94117 100644 --- a/modules/namespace-test-cs/libraries/AuthLib/Scheduled.cs +++ b/modules/namespace-test-cs/libraries/AuthLib/Scheduled.cs @@ -108,9 +108,13 @@ public static void ReducerTick(ReducerContext ctx, ReducerJob job) ScheduledId = job.Id, }; if (previous is null) + { ctx.Db.ScheduleResult.Insert(result); + } else + { ctx.Db.ScheduleResult.JobId.Update(result); + } } [Procedure(Name = "run_procedure_job")] @@ -128,9 +132,14 @@ public static void ProcedureTick(ProcedureContext ctx, ProcedureJob job) ScheduledId = job.Id, }; if (previous is null) + { tx.Db.ScheduleResult.Insert(result); + } else + { tx.Db.ScheduleResult.JobId.Update(result); + } + return 0; }); } @@ -140,7 +149,10 @@ public static void CancelSchedules(ReducerContext ctx) { var repeat = ctx.Db.ScheduleResult.JobId.Find(5)!.Value; if (repeat.Executions < 2) + { throw new Exception("Repeating schedule has not run twice."); + } + ctx.Db.ReducerJob.Id.Delete(repeat.ScheduledId); ctx.Db.ScheduleResult.Insert( new ScheduleResult diff --git a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs index 75d82fbf800..aa50be90ba1 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs @@ -10,7 +10,9 @@ internal static class Program private static void Require(bool condition, string message) { if (!condition) + { throw new Exception(message); + } } private static void Main() @@ -18,7 +20,10 @@ private static void Main() var host = Environment.GetEnvironmentVariable("SPACETIMEDB_SERVER_URL") ?? "http://localhost:3000"; if (host == "local") + { host = "http://localhost:3000"; + } + var connected = false; Exception? connectionError = null; var conn = DbConnection @@ -38,14 +43,22 @@ void Wait(Func done, string phase) while (!done()) { if (connectionError != null) + { throw connectionError; + } + if (timer.Elapsed > TimeSpan.FromSeconds(30)) + { throw new TimeoutException(phase); + } + conn.FrameTick(); Thread.Sleep(5); } if (connectionError != null) + { throw connectionError; + } } void Unsubscribe(SubscriptionHandle handle) @@ -122,7 +135,10 @@ void EmptyCache() conn.Db.User.OnInsert += (ctx, row) => { if (row.Id != 2) + { return; + } + Require( ctx.Db.MyAuth.User.Id.Find(2)?.Score == 99 && ctx.Db.@class.User.Id.Find(4)?.Message == "consumer", @@ -301,7 +317,10 @@ void EmptyCache() conn.Db.MyAuth.User.OnDelete += (ctx, row) => { if (row.Id != 10) + { return; + } + Require( ctx.Db.MyAuth.User.Id.Find(10) == null && ctx.Db.@class.User.Id.Find(10) != null, @@ -457,7 +476,10 @@ uint payloadBase void CheckTransactionInsert(EventContext ctx, uint id) { if (id < 20) + { return; + } + Require(id == 20, "A rolled-back procedure emitted an insert"); Require( ctx.Db.User.Id.Find(id) != null diff --git a/sdks/csharp/examples~/regression-tests/namespaces/RootRlsTests.cs b/sdks/csharp/examples~/regression-tests/namespaces/RootRlsTests.cs index 7227a9e2152..7fa657e8fec 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/RootRlsTests.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/RootRlsTests.cs @@ -10,7 +10,9 @@ internal static class RootRlsTests private static void Require(bool condition, string message) { if (!condition) + { throw new Exception(message); + } } public static void Run(string host) @@ -39,15 +41,23 @@ void Wait(Func done, string phase) while (!done()) { if (error != null) + { throw error; + } + if (timer.Elapsed > TimeSpan.FromSeconds(30)) + { throw new TimeoutException("Root RLS: " + phase); + } + first.FrameTick(); second.FrameTick(); Thread.Sleep(5); } if (error != null) + { throw error; + } } try diff --git a/sdks/csharp/src/Table.cs b/sdks/csharp/src/Table.cs index f841112374b..3224b82d42a 100644 --- a/sdks/csharp/src/Table.cs +++ b/sdks/csharp/src/Table.cs @@ -454,7 +454,11 @@ void IRemoteTableHandle.PreApply(IEventContext context, IParsedTableUpdate parse { // Fully qualified to avoid clash with UnityEngine.Debug System.Diagnostics.Debug.Assert(wasInserted.Count == 0 && wasUpdated.Count == 0 && wasRemoved.Count == 0, "Call Apply and PostApply before calling PreApply again"); - if (IsEventTable) return; // Event tables have no deletes. + if (IsEventTable) + { + return; // Event tables have no deletes. + } + var delta = (ParsedTableUpdate)parsedTableUpdate; foreach (var (_, value) in Entries.WillRemove(delta.Delta)) { From 894390c0b0013e592ecc4750935de1e72bfbe835 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 13:29:26 -0500 Subject: [PATCH 41/49] Move ModuleDescriptorAttribute to only .NET 10 --- crates/bindings-csharp/Runtime/Attrs.cs | 42 ++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/crates/bindings-csharp/Runtime/Attrs.cs b/crates/bindings-csharp/Runtime/Attrs.cs index e1b2ad9c340..2c8e53a8af0 100644 --- a/crates/bindings-csharp/Runtime/Attrs.cs +++ b/crates/bindings-csharp/Runtime/Attrs.cs @@ -1,26 +1,5 @@ namespace SpacetimeDB { -#if NET10_0_OR_GREATER - /// - /// Places the module contributions of the marker type's assembly in a namespace. - /// The consuming module chooses the placement; the marker may be any accessible type. - /// Requires .NET 10 and C# 14. - /// - /// - /// An assembly may be mounted only once. Dependencies cannot declare mounts. - /// Named namespaces cannot contain lifecycle reducers, RLS filters, or nonempty - /// environment declarations. Dependencies without a mount register automatically in public. - /// - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class NamespaceAttribute(System.Type marker) : Attribute - { - public System.Type Marker { get; } = marker; - - /// The C# member name and database namespace used for the mounted module. - public string Accessor { get; set; } = ""; - } -#endif - /// Declares the complete environment schema for this module. [AttributeUsage(AttributeTargets.Struct)] public sealed class EnvAttribute : Attribute { } @@ -251,9 +230,30 @@ public sealed class HttpHandlerAttribute() : Attribute { } [AttributeUsage(AttributeTargets.Method, Inherited = false)] public sealed class HttpRouterAttribute() : Attribute { } +#if NET10_0_OR_GREATER [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)] public sealed class ModuleDescriptorAttribute(Type descriptorType) : Attribute { public Type DescriptorType { get; } = descriptorType; } + + /// + /// Places the module contributions of the marker type's assembly in a namespace. + /// The consuming module chooses the placement; the marker may be any accessible type. + /// Requires .NET 10 and C# 14. + /// + /// + /// An assembly may be mounted only once. Dependencies cannot declare mounts. + /// Named namespaces cannot contain lifecycle reducers, RLS filters, or nonempty + /// environment declarations. Dependencies without a mount register automatically in public. + /// + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class NamespaceAttribute(System.Type marker) : Attribute + { + public System.Type Marker { get; } = marker; + + /// The C# member name and database namespace used for the mounted module. + public string Accessor { get; set; } = ""; + } +#endif } From e7f6c995cbd4e852e8ea6456e33a4edfeb42e164 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 14:59:54 -0500 Subject: [PATCH 42/49] Run integration tests in both .NET 8 and .NET 10 clients --- crates/bindings-csharp/README.md | 8 ++------ sdks/csharp/DEVELOP.md | 14 ------------- .../regression-tests/namespaces/README.md | 20 ++++++++++--------- .../regression-tests/namespaces/client.csproj | 2 +- sdks/csharp/tools~/run-regression-tests.sh | 14 ++++++++----- 5 files changed, 23 insertions(+), 35 deletions(-) diff --git a/crates/bindings-csharp/README.md b/crates/bindings-csharp/README.md index 048091d2c52..63156857d65 100644 --- a/crates/bindings-csharp/README.md +++ b/crates/bindings-csharp/README.md @@ -48,7 +48,7 @@ AuthLib helpers continue to use `ctx.Db.User` and `ctx.From.User()`, regardless of the namespace selected by the root. Ordinary helper calls share the caller's context and transaction; a namespace is not a security boundary between helpers. -#### Current restrictions +#### Restrictions and limitations - Only the consuming root chooses namespace placement. A dependency that itself declares namespace mounts cannot be composed, even in `public`. Nested mounts, @@ -71,11 +71,7 @@ context and transaction; a namespace is not a security boundary between helpers. on to protect data. - HTTP routes retain the existing root-level routing and environment authority; mounting a dependency does not add an HTTP namespace prefix. -- Composition uses C# assemblies, not TypeScript or Rust module binaries. - Cross-language module composition is not implemented by this mechanism. - -These restrictions do not require C# 14 in clients. See -[C# namespace bindings](../../sdks/csharp/DEVELOP.md#namespace-bindings). +- Cross-language module composition is not currently supported. ### Declared environment diff --git a/sdks/csharp/DEVELOP.md b/sdks/csharp/DEVELOP.md index 18ec2b04d35..ba1f78c529d 100644 --- a/sdks/csharp/DEVELOP.md +++ b/sdks/csharp/DEVELOP.md @@ -63,20 +63,6 @@ while a `User` row in the `MyAuth` database namespace becomes `Game.Bindings.MyAuth.User`. Their table handles remain `conn.Db.User` and `conn.Db.MyAuth.User`, respectively. -Generated bindings and the SDK retain the C# 9 / .NET Standard 2.1 baseline; -the module's C# 14 extension properties are not used in clients. Namespace -containers share one connection and table cache. - -Typed queries such as `q.From.MyAuth.User()` quote namespace and table segments -separately. Raw SQL must use the same database namespace, for example -`SELECT * FROM "MyAuth"."user"` for a table whose SQL name is `user`. -There is no separate namespace alias or SQL-level namespace name. - -The C# client also supports schemas produced by TypeScript submodules. This does -not mean a C# module can reference a TypeScript module as an assembly dependency, -nor establish namespace support in other client SDKs. Module-side restrictions -are documented in the [C# bindings README](../../crates/bindings-csharp/README.md#current-restrictions). - ### Runtime Structure Most of the core logic of the SDK lives in [`DbConnectionBase<...>`](./src/SpacetimeDBClient.cs). This handles: diff --git a/sdks/csharp/examples~/regression-tests/namespaces/README.md b/sdks/csharp/examples~/regression-tests/namespaces/README.md index d574bb62552..236837fd125 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/README.md +++ b/sdks/csharp/examples~/regression-tests/namespaces/README.md @@ -1,10 +1,13 @@ # Namespace Integration Test -Runs a generated C# 9 / .NET 8 client against the .NET 10 module in -`modules/namespace-test-cs`. It uses `Accessor` as the namespace name throughout. +Runs generated clients against the .NET 10 module in `modules/namespace-test-cs`. +The .NET 8 run verifies backward compatibility; +the .NET 10 run verifies the newer client runtime. Both retain C# 9 to enforce the +generated-code language baseline. It uses `Accessor` as the namespace name throughout. The existing `sdks/csharp/tools~/run-regression-tests.sh 10` harness generates the -bindings, publishes a fresh `namespace-tests` database, and runs this client. +bindings and runs this client on both frameworks, clearing and republishing the +`namespace-tests` database before each run. The namespace scenario is skipped in the .NET 8 **module** pass. CI already runs both harness passes. @@ -13,8 +16,10 @@ C# packages configured as described in `sdks/csharp/DEVELOP.md`: ```sh cargo spacetime generate -y -l csharp -o sdks/csharp/examples~/regression-tests/namespaces/module_bindings --module-path modules/namespace-test-cs --build-options="--dotnet-version 10" -cargo spacetime publish --dotnet-version 10 -c -y --server local -p modules/namespace-test-cs namespace-tests -dotnet run --project sdks/csharp/examples~/regression-tests/namespaces/client.csproj +for framework in net8.0 net10.0; do + cargo spacetime publish --dotnet-version 10 -c -y --server local -p modules/namespace-test-cs namespace-tests + dotnet run --framework "$framework" --project sdks/csharp/examples~/regression-tests/namespaces/client.csproj +done ``` The publish command deletes existing data in the test database. Republish before @@ -23,7 +28,7 @@ each client run. For a nondefault server, pass its URL to publish and set Coverage: -- Root and two mounted libraries with different row types named `User`, plus an +- Root and two mounted libraries with different row types named `User`, plus a dependency automatically registered in `public`, without a namespace declaration. - Explicit table names and a C# keyword namespace accessor. - Typed subscriptions, filtered queries, both semijoin directions, and overlapping @@ -46,8 +51,5 @@ Coverage: execution, repeating reducer cancellation, argument payloads, generated keys, namespace isolation, and absence of scheduled functions from client call APIs. -Assertions throw in both Debug and Release. Every asynchronous phase has a timeout. -The generated bindings are committed and regenerated through the normal CLI path. - Environment access and namespace isolation are covered separately by `namespace_csharp_environment_security` in `crates/testing/tests/environment.rs`. diff --git a/sdks/csharp/examples~/regression-tests/namespaces/client.csproj b/sdks/csharp/examples~/regression-tests/namespaces/client.csproj index 1942262018f..719f2fd86d2 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/client.csproj +++ b/sdks/csharp/examples~/regression-tests/namespaces/client.csproj @@ -1,7 +1,7 @@ Exe - net8.0 + net8.0;net10.0 9 enable disable diff --git a/sdks/csharp/tools~/run-regression-tests.sh b/sdks/csharp/tools~/run-regression-tests.sh index b2cb3542c7b..f801a9b39f6 100644 --- a/sdks/csharp/tools~/run-regression-tests.sh +++ b/sdks/csharp/tools~/run-regression-tests.sh @@ -92,10 +92,11 @@ configure_csharp_modules_sdk() { run_client() { local dir="$1" local dotnet_version="$2" + shift 2 if [ "$dotnet_version" = "10" ]; then - (cd "$dir" && EXPERIMENTAL_WASM_AOT=1 dotnet run -c Debug) + (cd "$dir" && EXPERIMENTAL_WASM_AOT=1 dotnet run -c Debug "$@") else - (cd "$dir" && env -u EXPERIMENTAL_WASM_AOT dotnet run -c Debug) + (cd "$dir" && env -u EXPERIMENTAL_WASM_AOT dotnet run -c Debug "$@") fi } @@ -132,8 +133,11 @@ for dotnet_version in "${DOTNET_VERSIONS[@]}"; do run_client "$SDK_PATH/examples~/regression-tests/procedure-client" "$dotnet_version" if [ "$dotnet_version" = "10" ]; then - cargo spacetime publish --dotnet-version 10 -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$STDB_PATH/modules/namespace-test-cs" namespace-tests - # The module needs .NET 10; its generated client deliberately stays on C# 9 / .NET 8. - run_client "$SDK_PATH/examples~/regression-tests/namespaces" 8 + # The module needs .NET 10; test its C# 9 bindings on both client runtimes. + for client_version in 8 10; do + echo "Running namespace client with .NET $client_version against the .NET 10 module" + cargo spacetime publish --dotnet-version 10 -c -y --server "$SPACETIMEDB_SERVER_URL" -p "$STDB_PATH/modules/namespace-test-cs" namespace-tests + run_client "$SDK_PATH/examples~/regression-tests/namespaces" "$client_version" --framework "net$client_version.0" + done fi done From b5028b6fd3fb50495098dc4cea1608575c646fb4 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 16:01:31 -0500 Subject: [PATCH 43/49] Fix module with RLS rules being ignored --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 49 +++++++++++++------ crates/bindings-csharp/Codegen/Module.cs | 1 + 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 2804f3c8cd2..c454e44ea45 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -746,15 +746,24 @@ public static class Rules { } ) { - var dependency = Emit( - Generate( - Create( - "RestrictedDependency", - "[SpacetimeDB.Table] public partial struct Entry { public uint Id; }\n" - + source - ) - ) + // These declarations must register even without tables or functions in the assembly. + var dependencyCompilation = Generate( + Create("RestrictedDependency", source + "\npublic class Entry { }") ); + var dependencyDescriptor = Descriptor(dependencyCompilation); + var dependency = Emit(dependencyCompilation); + if (declaration == "row-level security filters") + { + Assert.Contains( + Method(dependencyCompilation, "Register") + .DescendantNodes() + .OfType(), + call => + call.Expression.ToString() == "builder.RegisterClientVisibilityFilter" + && call.ArgumentList.Arguments.Single().ToString() + == "global::Rules.Visible" + ); + } var result = CSharpGeneratorDriver .Create([new Module().AsSourceGenerator()], parseOptions: fixture.ParseOptions) .RunGenerators( @@ -774,14 +783,24 @@ public static class Rules { && diagnostic.GetMessage().Contains(declaration) && diagnostic.GetMessage().Contains("root scope") ); - Generate(Create("FlatConsumer", "", dependency)); - Generate( - Create( - "PublicConsumer", + foreach ( + var mount in new[] + { + "", "[assembly: SpacetimeDB.Namespace(typeof(Entry), Accessor = \"public\")]", - dependency - ) - ); + } + ) + { + var consumer = Generate(Create("PublicConsumer", mount, dependency)); + Assert.Equal( + new[] + { + Descriptor(consumer) + ".Register", + dependencyDescriptor + ".Register", + }, + Calls(consumer) + ); + } } // Empty environment schemas contain no keys and are permitted by the host. diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 48b29c4c682..d9581862c4e 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -3197,6 +3197,7 @@ void Add(string name, string owner, string declaration) && addProcedures.Array.IsEmpty && addHttpHandlers.Array.IsEmpty && views.Array.IsEmpty + && rlsFilters.Array.IsEmpty && assemblies.Array.IsEmpty && !hasEnvironment ) From 9977afe662ed9752da96dc58a8c0a376819785f5 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 16:07:20 -0500 Subject: [PATCH 44/49] Preserve flat accessors for dependencies mounted as "public" --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 37 +++++++++++++++++++ crates/bindings-csharp/Codegen/Module.cs | 3 +- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index c454e44ea45..77d8232b823 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -655,6 +655,43 @@ .. Method(compilation, "Initialize") return; } + foreach (var accessor in new[] { "public", "PUBLIC" }) + { + var publicConsumer = Generate( + Create( + "PublicAccessorConsumer", + $$""" + [assembly: SpacetimeDB.Namespace(typeof(Alpha.Sentinel), Accessor = "{{accessor}}")] + public static class Helpers { + public static void Insert(SpacetimeDB.ReducerContext ctx) => + ctx.Db.AlphaRow.Insert(new Alpha.AlphaRow { Id = 1 }); + public static ulong Count(SpacetimeDB.ViewContext ctx) => ctx.Db.AlphaRow.Count; + public static ulong Count(SpacetimeDB.AnonymousViewContext ctx) => ctx.Db.AlphaRow.Count; + public static SpacetimeDB.IQuery Query(SpacetimeDB.ViewContext ctx) => + ctx.From.AlphaRow(); + public static SpacetimeDB.IQuery Query(SpacetimeDB.AnonymousViewContext ctx) => + ctx.From.AlphaRow(); + } + """, + alpha, + shared + ) + ); + Assert.Equal( + new[] + { + Descriptor(publicConsumer) + ".Register", + Descriptor(alphaCompilation) + ".Register", + Descriptor(sharedCompilation) + ".Register", + }, + Calls(publicConsumer) + ); + Assert.DoesNotContain( + "RegisterSubmodule", + Method(publicConsumer, "Initialize").ToString() + ); + } + // An unrelated utility alone must not cause an otherwise empty module to register. var plainUtility = Emit(Create("PlainUtility", "public class PlainUtility { }")); var empty = Generate(Create("Empty", "", plainUtility)); diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index d9581862c4e..8819dccb7aa 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -3030,8 +3030,9 @@ void Add(string name, string owner, string declaration) } foreach (var assembly in assemblies) { - if (mountByIdentity.TryGetValue(assembly.Identity, out var mount)) + if (IsChild(assembly)) { + var mount = mountByIdentity[assembly.Identity]; Add( mount.Accessor, assembly.Identity, From afe779842ec5b75c6647210f796ee74c18eefbd2 Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 16:22:21 -0500 Subject: [PATCH 45/49] Fix public dependency overriding root's case policy --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 68 +++++++++++++++++++ .../ExtraCompilationErrors.net10.verified.txt | 4 +- .../diag/snapshots/Module#FFI.verified.cs | 1 + .../snapshots/Module.net10#FFI.verified.cs | 1 + .../snapshots/Module#FFI.verified.cs | 1 + .../snapshots/Module.net10#FFI.verified.cs | 1 + .../server/snapshots/Module#FFI.verified.cs | 1 + .../snapshots/Module.net10#FFI.verified.cs | 1 + crates/bindings-csharp/Codegen/Diag.cs | 14 ++++ crates/bindings-csharp/Codegen/Module.cs | 35 ++++++++-- crates/bindings-csharp/README.md | 3 + 11 files changed, 123 insertions(+), 7 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 77d8232b823..ac49e032a1f 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -692,6 +692,74 @@ public static void Insert(SpacetimeDB.ReducerContext ctx) => ); } + string Policy(string? policy) => + policy is null + ? "" + : $$""" + public static class NamingSettings { + [SpacetimeDB.Settings] + public const SpacetimeDB.CaseConversionPolicy Naming = SpacetimeDB.CaseConversionPolicy.{{policy}}; + } + """; + foreach ( + var (rootPolicy, dependencyPolicy) in new (string?, string?)[] + { + ("SnakeCase", "None"), + (null, "None"), + ("None", "SnakeCase"), + ("None", "None"), + ("SnakeCase", "SnakeCase"), + (null, "SnakeCase"), + ("None", null), + } + ) + { + var dependency = Emit( + Generate( + Create("PolicyDependency", Table("PolicyDependency") + Policy(dependencyPolicy)) + ) + ); + foreach (var mount in new[] { "", "public", "Named" }) + { + var source = + ( + mount.Length == 0 + ? "" + : $"[assembly: SpacetimeDB.Namespace(typeof(PolicyDependency.Sentinel), Accessor = \"{mount}\")]\n" + ) + Policy(rootPolicy); + var compilation = Create("PolicyConsumer", source, dependency); + if ( + mount != "Named" + && dependencyPolicy is not null + && dependencyPolicy != (rootPolicy ?? "SnakeCase") + ) + { + var result = CSharpGeneratorDriver + .Create( + [new Module().AsSourceGenerator()], + parseOptions: fixture.ParseOptions + ) + .RunGenerators(compilation) + .GetRunResult(); + Assert.Contains( + result.Diagnostics, + diagnostic => + diagnostic.Severity == DiagnosticSeverity.Error + && diagnostic.Descriptor.Title.ToString() + == "Conflicting case conversion policies" + && diagnostic.GetMessage().Contains("PolicyConsumer") + && diagnostic.GetMessage().Contains("PolicyDependency") + && diagnostic.GetMessage().Contains("SnakeCase") + && diagnostic.GetMessage().Contains("None") + ); + } + else + { + Generate(compilation); + } + } + } + // An unrelated utility alone must not cause an otherwise empty module to register. var plainUtility = Emit(Create("PlainUtility", "public class PlainUtility { }")); var empty = Generate(Create("Empty", "", plainUtility)); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt index d528135ba94..e6f8b198379 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.net10.verified.txt @@ -396,7 +396,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(808)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1030)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(809)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1031)]', Severity: Error, Descriptor: { Id: CS0121, @@ -419,7 +419,7 @@ public partial struct TestDefaultFieldValues ^^^^^^^^^^^^^^^^^^^^^^ } */ - Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(808)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1030)]', + Message: The call is ambiguous between the following methods or properties: 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(809)]' and 'SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Queries.TestDuplicateTableName() [{ProjectDirectory}fixtures/diag/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs(1031)]', Severity: Error, Descriptor: { Id: CS0121, diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs index a86b0ad8703..03f101af3fe 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs @@ -937,6 +937,7 @@ namespace SpacetimeDB.Generated.diag_4F830E2879BB50E3 { public static partial class AssemblyDescriptor { + public const string? CaseConversionPolicy = "SnakeCase"; public const string RootOnlyDeclarations = "row-level security filters, lifecycle reducer Reducers.TestDuplicateReducerKind1 (Init), lifecycle reducer Reducers.TestDuplicateReducerKind2 (Init)"; public const int ReducerCount = 8; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs index 7ddb7d50f5d..f62e4bd27d2 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs @@ -939,6 +939,7 @@ namespace SpacetimeDB.Generated.diag_4F830E2879BB50E3 { public static partial class AssemblyDescriptor { + public const string? CaseConversionPolicy = "SnakeCase"; public const string RootOnlyDeclarations = "row-level security filters, lifecycle reducer Reducers.TestDuplicateReducerKind1 (Init), lifecycle reducer Reducers.TestDuplicateReducerKind2 (Init)"; public const int ReducerCount = 8; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs index aa01b3f4454..b5fdecd9cfb 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs @@ -320,6 +320,7 @@ namespace SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31 { public static partial class AssemblyDescriptor { + public const string? CaseConversionPolicy = "SnakeCase"; public const string RootOnlyDeclarations = ""; public const int ReducerCount = 1; public const int ProcedureCount = 1; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs index a7409943015..b81c8891f1d 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs @@ -321,6 +321,7 @@ namespace SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31 { public static partial class AssemblyDescriptor { + public const string? CaseConversionPolicy = "SnakeCase"; public const string RootOnlyDeclarations = ""; public const int ReducerCount = 1; public const int ProcedureCount = 1; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs index eb2231687db..e01409c8b42 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs @@ -771,6 +771,7 @@ namespace SpacetimeDB.Generated.server_D513E4815F57969C { public static partial class AssemblyDescriptor { + public const string? CaseConversionPolicy = null; public const string RootOnlyDeclarations = "row-level security filters, environment variables, lifecycle reducer Timers.Init (Init)"; public const int ReducerCount = 6; diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs index 5150e08e255..2018d59eb3e 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs @@ -777,6 +777,7 @@ namespace SpacetimeDB.Generated.server_D513E4815F57969C { public static partial class AssemblyDescriptor { + public const string? CaseConversionPolicy = null; public const string RootOnlyDeclarations = "row-level security filters, environment variables, lifecycle reducer Timers.Init (Init)"; public const int ReducerCount = 6; diff --git a/crates/bindings-csharp/Codegen/Diag.cs b/crates/bindings-csharp/Codegen/Diag.cs index 8f1e7498a94..269e59d5b14 100644 --- a/crates/bindings-csharp/Codegen/Diag.cs +++ b/crates/bindings-csharp/Codegen/Diag.cs @@ -423,4 +423,18 @@ string second $"Generated C# name '{ctx.scope}.{ctx.name}' is used by both {ctx.first} and {ctx.second}. Choose distinct accessors or member names.", ctx => ctx.location ); + + public static readonly ErrorDescriptor<( + string root, + string rootPolicy, + string dependency, + string dependencyPolicy + )> ConflictingCaseConversionPolicies = + new( + group, + "Conflicting case conversion policies", + ctx => + $"Root assembly '{ctx.root}' uses case conversion policy '{ctx.rootPolicy}', but dependency '{ctx.dependency}' declares '{ctx.dependencyPolicy}' in the shared public scope. Use the same policy, remove the dependency's setting to inherit the root policy, or mount the dependency in a distinct namespace.", + _ => Location.None + ); } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 8819dccb7aa..e8c8e55b2b9 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -2285,6 +2285,7 @@ record AssemblyDeclaration( string DescriptorTypeName, bool DeclaresMounts, string RootOnlyDeclarations, + string? CaseConversionPolicy, EquatableArray Tables, EquatableArray ReadOnlyTables, EquatableArray Queries @@ -2396,6 +2397,11 @@ marker is null .FirstOrDefault() ?.ConstantValue as string ?? "", + descriptor + .GetMembers("CaseConversionPolicy") + .OfType() + .FirstOrDefault() + ?.ConstantValue as string, ReadAccessors("Tables"), ReadAccessors("ReadOnlyTables"), new( @@ -3112,11 +3118,29 @@ void Add(string name, string owner, string declaration) ); } - var settingsRegistration = - settings.Array.Length == 1 - && settings.Array[0].CaseConversionPolicy is { } policyName - ? $"builder.SetCaseConversionPolicy(SpacetimeDB.CaseConversionPolicy.{policyName});" - : string.Empty; + var declaredCasePolicy = + settings.Array.Length == 1 ? settings.Array[0].CaseConversionPolicy : null; + // A shared typespace also has one naming policy. Unspecified dependency + // settings inherit the root policy, whose host default is SnakeCase. + var rootCasePolicy = declaredCasePolicy ?? "SnakeCase"; + foreach (var assembly in publicScopeAssemblies) + { + if ( + assembly.CaseConversionPolicy is { } dependencyPolicy + && dependencyPolicy != rootCasePolicy + ) + { + context.ReportDiagnostic( + ErrorDescriptor.ConflictingCaseConversionPolicies.ToDiag( + (identity, rootCasePolicy, assembly.Identity, dependencyPolicy) + ) + ); + } + } + + var settingsRegistration = declaredCasePolicy is { } policyName + ? $"builder.SetCaseConversionPolicy(SpacetimeDB.CaseConversionPolicy.{policyName});" + : string.Empty; var explicitTableRegistrations = string.Join( "\n", @@ -3466,6 +3490,7 @@ internal AnonymousViewContext(Internal.LocalReadOnly db) #if NET10_0_OR_GREATER namespace {{extensionNamespaceName}} { public static partial class AssemblyDescriptor { + public const string? CaseConversionPolicy = {{(declaredCasePolicy is null ? "null" : SymbolDisplay.FormatLiteral(declaredCasePolicy, true))}}; public const string RootOnlyDeclarations = {{SymbolDisplay.FormatLiteral(string.Join(", ", new[] { rlsFilters.Array.Length != 0 ? "row-level security filters" : null, environmentRegistrations.Length != 0 ? "environment variables" : null diff --git a/crates/bindings-csharp/README.md b/crates/bindings-csharp/README.md index 63156857d65..da9368fe809 100644 --- a/crates/bindings-csharp/README.md +++ b/crates/bindings-csharp/README.md @@ -56,6 +56,9 @@ context and transaction; a namespace is not a security boundary between helpers. - An assembly can be mounted only once, and the root cannot mount itself. Omitting the attribute, or explicitly using `Accessor = "public"`, registers the dependency in the default scope with flat accessors. +- Dependencies in `public` inherit the root's case-conversion policy (`SnakeCase` + by default). An explicitly different policy is a compilation error. Mount the + dependency in a named namespace to keep its independent naming policy. - `Accessor` is currently both the C# accessor and database namespace. There is no separate SQL-level `Name`. It must be a valid C# and database identifier, at most 63 UTF-8 bytes. Names are checked for case-insensitive duplicates; From 2025539bb2b645718bb9f305106c40fc52d7b3af Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Thu, 24 Sep 2026 16:41:00 -0500 Subject: [PATCH 46/49] Fix HTTP handlers collisions across assemblies --- crates/bindings-csharp/Codegen.Tests/Tests.cs | 21 +++++++++++++++++++ .../snapshots/Module.net10#FFI.verified.cs | 2 +- .../snapshots/Module.net10#FFI.verified.cs | 2 +- .../snapshots/Module.net10#FFI.verified.cs | 2 +- crates/bindings-csharp/Codegen/Module.cs | 2 +- modules/namespace-test-cs/Lib.cs | 2 +- .../libraries/AuthLib/Lib.cs | 3 +-- 7 files changed, 27 insertions(+), 7 deletions(-) diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index ac49e032a1f..6afa1ae3b82 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -692,6 +692,27 @@ public static void Insert(SpacetimeDB.ReducerContext ctx) => ); } + string HttpModule(string name) => + $$""" + namespace {{name}}Module { + using SpacetimeDB; + public static partial class Functions { + [HttpHandler] + public static HttpResponse {{name}}(HandlerContext ctx, HttpRequest request) => + throw new Exception(); + [HttpRouter] + public static Router Routes() => Router.New() + .Get("/short", Handlers.{{name}}) + .Get("/qualified", global::SpacetimeDB.Handlers.{{name}}); + } + } + """; + // The library references a table-only module, which also generates a Handlers container. + var httpLibrary = Emit( + Generate(Create("HttpLibrary", HttpModule("LibraryHandler"), alpha, shared)) + ); + Generate(Create("HttpConsumer", HttpModule("RootHandler"), httpLibrary, alpha, shared)); + string Policy(string? policy) => policy is null ? "" diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs index f62e4bd27d2..fa1f70ee12b 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs @@ -654,7 +654,7 @@ public readonly partial struct QueryBuilder } #endif - public static class Handlers { } + internal static class Handlers { } #if !NET10_0_OR_GREATER public sealed record ReducerContext : DbContext, Internal.IReducerContext diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs index b81c8891f1d..03cd1496cf1 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs @@ -56,7 +56,7 @@ public readonly partial struct QueryBuilder } #endif - public static class Handlers { } + internal static class Handlers { } #if !NET10_0_OR_GREATER public sealed record ReducerContext : DbContext, Internal.IReducerContext diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs index 2018d59eb3e..1ea6cc84824 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs @@ -498,7 +498,7 @@ public readonly partial struct QueryBuilder } #endif - public static class Handlers { } + internal static class Handlers { } #if !NET10_0_OR_GREATER public sealed record ReducerContext : DbContext, Internal.IReducerContext diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index e8c8e55b2b9..8c700d47093 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -3256,7 +3256,7 @@ namespace SpacetimeDB { #if !NET10_0_OR_GREATER {{IndentGeneratedCode(queryBuilderMembers, 4)}} #endif - public static class Handlers { + internal static class Handlers { {{IndentGeneratedCode(string.Join("\n", addHttpHandlers.Select(r => $"public static readonly global::SpacetimeDB.Handler {EscapeIdentifier(r.Name)} = new(nameof({r.FullName}));" )), 8)}} diff --git a/modules/namespace-test-cs/Lib.cs b/modules/namespace-test-cs/Lib.cs index 6e70ffd6ad8..73a8938dc80 100644 --- a/modules/namespace-test-cs/Lib.cs +++ b/modules/namespace-test-cs/Lib.cs @@ -36,7 +36,7 @@ public static HttpResponse RootAuthCount(HandlerContext ctx, HttpRequest request [HttpRouter] public static Router Routes() => - Router.New().Get("/root-auth-count", new Handler(nameof(RootAuthCount))); + Router.New().Get("/root-auth-count", SpacetimeDB.Handlers.RootAuthCount); #pragma warning disable STDB_UNSTABLE [ClientVisibilityFilter] diff --git a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs index 080d2a57f3a..9f4db5a0680 100644 --- a/modules/namespace-test-cs/libraries/AuthLib/Lib.cs +++ b/modules/namespace-test-cs/libraries/AuthLib/Lib.cs @@ -112,6 +112,5 @@ public static HttpResponse AuthCount(HandlerContext ctx, HttpRequest request) => ); [HttpRouter] - public static Router Routes() => - Router.New().Get("/auth-count", new Handler(nameof(AuthCount))); + public static Router Routes() => Router.New().Get("/auth-count", Handlers.AuthCount); } From fa97ddc7df13b4564cd62a9d4018da5d481c7e7c Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Fri, 25 Sep 2026 13:52:04 -0500 Subject: [PATCH 47/49] Use canonical names --- TESTING.md | 11 +- crates/bindings-csharp/Codegen.Tests/Tests.cs | 25 ++- .../diag/snapshots/Module#FFI.verified.cs | 5 +- .../snapshots/Module.net10#FFI.verified.cs | 3 +- ...space.TestDuplicateReducerName.verified.cs | 10 +- ...rs.OnReducerWithReservedPrefix.verified.cs | 10 +- ...cers.TestDuplicateReducerKind1.verified.cs | 10 +- ...cers.TestDuplicateReducerKind2.verified.cs | 10 +- ...ucers.TestDuplicateReducerName.verified.cs | 10 +- ...Reducers.TestReducerReturnType.verified.cs | 10 +- ...cers.TestReducerWithoutContext.verified.cs | 10 +- ...rs.__ReducerWithReservedPrefix.verified.cs | 10 +- ...leIssues.DummyScheduledReducer.verified.cs | 10 +- .../snapshots/Module#FFI.verified.cs | 5 +- .../snapshots/Module.net10#FFI.verified.cs | 3 +- ...e.net10#Reducers.DemoProcedure.verified.cs | 10 +- ...ule.net10#Reducers.DemoReducer.verified.cs | 10 +- .../server/snapshots/Module#FFI.verified.cs | 5 +- .../snapshots/Module.net10#FFI.verified.cs | 3 +- ...#MultiTableRow.InsertMultiData.verified.cs | 10 +- ...dule.net10#Reducers.InsertData.verified.cs | 10 +- ...t10#Reducers.ScheduleImmediate.verified.cs | 10 +- ...espaces.AndClasses.InsertData2.verified.cs | 10 +- .../Module.net10#Timers.Init.verified.cs | 10 +- ...10#Timers.SendScheduledMessage.verified.cs | 10 +- crates/bindings-csharp/Codegen/Module.cs | 21 +-- .../Codegen/NamespaceDeclaration.cs | 96 ++++++---- crates/bindings-csharp/README.md | 20 ++- crates/bindings-csharp/Runtime/Attrs.cs | 8 +- .../Runtime/Internal/CanonicalName.cs | 169 ++++++++++++++++++ .../Runtime/Internal/Module.cs | 10 ++ .../Runtime/Internal/ModuleBuilder.cs | 10 +- .../Runtime/Internal/NamespaceRegistry.cs | 53 +++++- crates/codegen/src/csharp.rs | 99 +++++----- crates/codegen/tests/codegen.rs | 8 +- crates/testing/tests/environment.rs | 11 +- .../tests/standalone_integration_test.rs | 69 +++++++ modules/namespace-test-cs/Lib.cs | 32 +++- sdks/csharp/DEVELOP.md | 10 +- .../regression-tests/namespaces/Program.cs | 9 +- .../regression-tests/namespaces/README.md | 9 +- .../namespaces/RootRlsTests.cs | 2 +- .../MyAuth/Procedures/CountUsers.g.cs | 2 +- .../MyAuth/Procedures/ReadScore.g.cs | 2 +- .../module_bindings/MyAuth/Reducers/Add.g.cs | 2 +- .../MyAuth/Reducers/CancelSchedules.g.cs | 2 +- .../module_bindings/MyAuth/Reducers/Fail.g.cs | 2 +- .../MyAuth/Reducers/Remove.g.cs | 2 +- .../MyAuth/Reducers/StartSchedules.g.cs | 2 +- .../MyAuth/Reducers/Update.g.cs | 2 +- .../MyAuth/Tables/AnonymousUsers.g.cs | 4 +- .../module_bindings/MyAuth/Tables/Notice.g.cs | 4 +- .../MyAuth/Tables/ProtectedRow.g.cs | 4 +- .../MyAuth/Tables/QueryUsers.g.cs | 4 +- .../MyAuth/Tables/ScheduleResult.g.cs | 4 +- .../module_bindings/MyAuth/Tables/User.g.cs | 4 +- .../module_bindings/MyAuth/Tables/Users.g.cs | 4 +- .../Procedures/ResolveScheduleName.g.cs | 101 +++++++++++ .../module_bindings/SpacetimeDBClient.g.cs | 2 +- 59 files changed, 778 insertions(+), 235 deletions(-) create mode 100644 crates/bindings-csharp/Runtime/Internal/CanonicalName.cs create mode 100644 sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/ResolveScheduleName.g.cs diff --git a/TESTING.md b/TESTING.md index b8707089c0f..e18a2f4a38b 100644 --- a/TESTING.md +++ b/TESTING.md @@ -106,14 +106,17 @@ The namespace tests are integration tests, plus focused generator diagnostics: checks mount restrictions, generated-name diagnostics, and dependency discovery. - `cargo test -p spacetimedb-testing --test standalone_integration_test namespace_csharp`: independent dependency publication, root export selection, and cross-namespace - helper/HTTP calls. + helper/HTTP calls, and runtime name conversion compared with host validation. - `cargo test -p spacetimedb-testing --test environment namespace_csharp_environment_security`: - root/public environment access and denial of namespaced host calls. + root/public environment access, denial of namespaced host calls, and default + namespace case conversion when `Name` is omitted. - `cargo test -p spacetimedb-codegen --test codegen`: codegen snapshots and a - generated C# client for a TypeScript submodule. + generated C# client for a TypeScript submodule, including distinct accessor + and canonical names. - The [namespace client regression](sdks/csharp/examples~/regression-tests/namespaces/README.md) runs against the real .NET 10 module and covers tables, queries, subscriptions, - callbacks, scheduling, transactions, and root-defined RLS. The existing + callbacks, scheduling, transactions, and root-defined RLS with + `Accessor = "MyAuth", Name = "auth_data"`. The existing `sdks/csharp/tools~/run-regression-tests.sh 8 10` harness includes it in the .NET 10 module pass while retaining .NET 8 regressions. diff --git a/crates/bindings-csharp/Codegen.Tests/Tests.cs b/crates/bindings-csharp/Codegen.Tests/Tests.cs index 6afa1ae3b82..5d24a28392b 100644 --- a/crates/bindings-csharp/Codegen.Tests/Tests.cs +++ b/crates/bindings-csharp/Codegen.Tests/Tests.cs @@ -319,8 +319,12 @@ out var diagnostics } var auth = Dependency("Auth"); var audit = Dependency("Audit"); - string Mount(string marker = "Auth.Marker", string accessor = "MyAuth") => - $"[assembly: SpacetimeDB.Namespace(typeof({marker}), Accessor = \"{accessor}\")]\n"; + string Mount( + string marker = "Auth.Marker", + string accessor = "MyAuth", + string? name = null + ) => + $"[assembly: SpacetimeDB.Namespace(typeof({marker}), Accessor = \"{accessor}\"{(name is null ? "" : ", Name = " + SymbolDisplay.FormatLiteral(name, true))})]\n"; GeneratorDriver Run(string source) => CSharpGeneratorDriver .Create( @@ -352,6 +356,14 @@ .. driver ]; Assert.Empty(Run(Mount(accessor: new string('a', 63))).GetRunResult().Diagnostics); Assert.Empty(Run(Mount(accessor: "public")).GetRunResult().Diagnostics); + Assert.Empty(Run(Mount(name: new string('a', 63))).GetRunResult().Diagnostics); + Assert.Empty(Run(Mount(accessor: "PUBLIC", name: "public")).GetRunResult().Diagnostics); + Assert.Empty(Run(Mount(name: "class")).GetRunResult().Diagnostics); + Reject(Mount(name: new string('a', 64)), "63 UTF-8 bytes"); + Reject(Mount(name: ""), "Name must be a nonempty database identifier"); + Reject(Mount(name: "st"), "reserved"); + Reject(Mount(accessor: "public", name: "auth_data"), "public scope"); + Reject(Mount(name: "PUBLIC"), "public scope"); Reject(Mount(accessor: new string('a', 64)), "63 UTF-8 bytes"); foreach (var name in new[] { "", "auth.data", "a-b", "1auth", " auth" }) Reject(Mount(accessor: name), "database identifier"); @@ -388,7 +400,14 @@ .. driver ); var original = Run(Mount()); - foreach (var source in new[] { Mount(accessor: "Other"), Mount(accessor: "class") }) + foreach ( + var source in new[] + { + Mount(accessor: "Other"), + Mount(accessor: "class"), + Mount(name: "auth_data"), + } + ) { var changed = original.RunGenerators(Create("Consumer", source, auth, audit)); Assert.Empty(changed.GetRunResult().Diagnostics); diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs index 03f101af3fe..249ea5f98a4 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs @@ -654,7 +654,7 @@ public readonly partial struct QueryBuilder } #endif - public static class Handlers { } + internal static class Handlers { } #if !NET10_0_OR_GREATER public sealed record ReducerContext : DbContext, Internal.IReducerContext @@ -4687,7 +4687,8 @@ internal static void Initialize() global::SpacetimeDB.Internal.Module.InstallNamespaces( new global::SpacetimeDB.Internal.NamespaceRegistry( "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - new global::System.Collections.Generic.KeyValuePair[] { } + global::SpacetimeDB.CaseConversionPolicy.SnakeCase, + new (string, string, string?, global::SpacetimeDB.CaseConversionPolicy)[] { } ) ); global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Register( diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs index fa1f70ee12b..34a847d2e03 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#FFI.verified.cs @@ -5098,7 +5098,8 @@ internal static void Initialize() global::SpacetimeDB.Internal.Module.InstallNamespaces( new global::SpacetimeDB.Internal.NamespaceRegistry( "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - new global::System.Collections.Generic.KeyValuePair[] { } + global::SpacetimeDB.CaseConversionPolicy.SnakeCase, + new (string, string, string?, global::SpacetimeDB.CaseConversionPolicy)[] { } ) ); global::SpacetimeDB.Generated.diag_4F830E2879BB50E3.AssemblyDescriptor.Register( diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.InAnotherNamespace.TestDuplicateReducerName.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.InAnotherNamespace.TestDuplicateReducerName.verified.cs index 96ae102944a..f8fde775eba 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.InAnotherNamespace.TestDuplicateReducerName.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.InAnotherNamespace.TestDuplicateReducerName.verified.cs @@ -8,10 +8,12 @@ partial class InAnotherNamespace { private static class __ScheduleTestDuplicateReducerNameName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(TestDuplicateReducerName) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestDuplicateReducerName), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleTestDuplicateReducerNameName() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.OnReducerWithReservedPrefix.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.OnReducerWithReservedPrefix.verified.cs index 0c87fdbea54..6a8071fa8dd 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.OnReducerWithReservedPrefix.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.OnReducerWithReservedPrefix.verified.cs @@ -6,10 +6,12 @@ partial class Reducers { private static class __ScheduleOnReducerWithReservedPrefixName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(OnReducerWithReservedPrefix) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(OnReducerWithReservedPrefix), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleOnReducerWithReservedPrefixName() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind1.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind1.verified.cs index 0fcda17d08b..05e5e398cba 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind1.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind1.verified.cs @@ -6,10 +6,12 @@ partial class Reducers { private static class __ScheduleTestDuplicateReducerKind1Name { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(TestDuplicateReducerKind1) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestDuplicateReducerKind1), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleTestDuplicateReducerKind1Name() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind2.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind2.verified.cs index 1130b799c6d..b1779d73fd8 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind2.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerKind2.verified.cs @@ -6,10 +6,12 @@ partial class Reducers { private static class __ScheduleTestDuplicateReducerKind2Name { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(TestDuplicateReducerKind2) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestDuplicateReducerKind2), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleTestDuplicateReducerKind2Name() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerName.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerName.verified.cs index dd21f02b945..865a64341ea 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerName.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestDuplicateReducerName.verified.cs @@ -6,10 +6,12 @@ partial class Reducers { private static class __ScheduleTestDuplicateReducerNameName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(TestDuplicateReducerName) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestDuplicateReducerName), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleTestDuplicateReducerNameName() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerReturnType.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerReturnType.verified.cs index 70eebe7d781..1bd50b93319 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerReturnType.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerReturnType.verified.cs @@ -6,10 +6,12 @@ partial class Reducers { private static class __ScheduleTestReducerReturnTypeName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(TestReducerReturnType) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestReducerReturnType), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleTestReducerReturnTypeName() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerWithoutContext.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerWithoutContext.verified.cs index f2a42b640ef..e1c79a74513 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerWithoutContext.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.TestReducerWithoutContext.verified.cs @@ -6,10 +6,12 @@ partial class Reducers { private static class __ScheduleTestReducerWithoutContextName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(TestReducerWithoutContext) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(TestReducerWithoutContext), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleTestReducerWithoutContextName() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.__ReducerWithReservedPrefix.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.__ReducerWithReservedPrefix.verified.cs index 0978d0cf077..e6bc0fee962 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.__ReducerWithReservedPrefix.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#Reducers.__ReducerWithReservedPrefix.verified.cs @@ -6,10 +6,12 @@ partial class Reducers { private static class __Schedule__ReducerWithReservedPrefixName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(__ReducerWithReservedPrefix) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(__ReducerWithReservedPrefix), + null + ); // Prevent eager initialization before the root installs namespace placements. static __Schedule__ReducerWithReservedPrefixName() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.DummyScheduledReducer.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.DummyScheduledReducer.verified.cs index c62d296ba4c..58d0fe081e9 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.DummyScheduledReducer.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module.net10#TestScheduleIssues.DummyScheduledReducer.verified.cs @@ -6,10 +6,12 @@ partial struct TestScheduleIssues { private static class __ScheduleDummyScheduledReducerName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(DummyScheduledReducer) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "diag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(DummyScheduledReducer), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleDummyScheduledReducerName() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs index b5fdecd9cfb..34632653434 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs @@ -56,7 +56,7 @@ public readonly partial struct QueryBuilder } #endif - public static class Handlers { } + internal static class Handlers { } #if !NET10_0_OR_GREATER public sealed record ReducerContext : DbContext, Internal.IReducerContext @@ -842,7 +842,8 @@ internal static void Initialize() global::SpacetimeDB.Internal.Module.InstallNamespaces( new global::SpacetimeDB.Internal.NamespaceRegistry( "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - new global::System.Collections.Generic.KeyValuePair[] { } + global::SpacetimeDB.CaseConversionPolicy.SnakeCase, + new (string, string, string?, global::SpacetimeDB.CaseConversionPolicy)[] { } ) ); global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.Register( diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs index 03cd1496cf1..71c39126665 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#FFI.verified.cs @@ -903,7 +903,8 @@ internal static void Initialize() global::SpacetimeDB.Internal.Module.InstallNamespaces( new global::SpacetimeDB.Internal.NamespaceRegistry( "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - new global::System.Collections.Generic.KeyValuePair[] { } + global::SpacetimeDB.CaseConversionPolicy.SnakeCase, + new (string, string, string?, global::SpacetimeDB.CaseConversionPolicy)[] { } ) ); global::SpacetimeDB.Generated.explicitnames_7C0F8C6449994F31.AssemblyDescriptor.Register( diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoProcedure.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoProcedure.verified.cs index 19fe4ca6d71..4db9a55c612 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoProcedure.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoProcedure.verified.cs @@ -6,10 +6,12 @@ partial class Reducers { private static class __ScheduleDemoProcedureName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "canonical_procedure" - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(DemoProcedure), + "canonical_procedure" + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleDemoProcedureName() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoReducer.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoReducer.verified.cs index 0a32e3cb75e..775f8b87ce6 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoReducer.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module.net10#Reducers.DemoReducer.verified.cs @@ -6,10 +6,12 @@ partial class Reducers { private static class __ScheduleDemoReducerName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - "canonical_reducer" - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "explicitnames, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(DemoReducer), + "canonical_reducer" + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleDemoReducerName() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs index e01409c8b42..b0436b146e4 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs @@ -498,7 +498,7 @@ public readonly partial struct QueryBuilder } #endif - public static class Handlers { } + internal static class Handlers { } #if !NET10_0_OR_GREATER public sealed record ReducerContext : DbContext, Internal.IReducerContext @@ -3468,7 +3468,8 @@ internal static void Initialize() global::SpacetimeDB.Internal.Module.InstallNamespaces( new global::SpacetimeDB.Internal.NamespaceRegistry( "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - new global::System.Collections.Generic.KeyValuePair[] { } + global::SpacetimeDB.CaseConversionPolicy.SnakeCase, + new (string, string, string?, global::SpacetimeDB.CaseConversionPolicy)[] { } ) ); global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.Register( diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs index 1ea6cc84824..395725f2581 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#FFI.verified.cs @@ -3827,7 +3827,8 @@ internal static void Initialize() global::SpacetimeDB.Internal.Module.InstallNamespaces( new global::SpacetimeDB.Internal.NamespaceRegistry( "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - new global::System.Collections.Generic.KeyValuePair[] { } + global::SpacetimeDB.CaseConversionPolicy.SnakeCase, + new (string, string, string?, global::SpacetimeDB.CaseConversionPolicy)[] { } ) ); global::SpacetimeDB.Generated.server_D513E4815F57969C.AssemblyDescriptor.Register( diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.InsertMultiData.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.InsertMultiData.verified.cs index f2f4796ce76..5549aba2925 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.InsertMultiData.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#MultiTableRow.InsertMultiData.verified.cs @@ -6,10 +6,12 @@ partial struct MultiTableRow { private static class __ScheduleInsertMultiDataName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(InsertMultiData) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(InsertMultiData), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleInsertMultiDataName() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.InsertData.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.InsertData.verified.cs index 8feb994bc57..1e2eafd9af6 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.InsertData.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.InsertData.verified.cs @@ -6,10 +6,12 @@ partial class Reducers { private static class __ScheduleInsertDataName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(InsertData) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(InsertData), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleInsertDataName() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.ScheduleImmediate.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.ScheduleImmediate.verified.cs index bc08c9e2acb..0200ad976db 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.ScheduleImmediate.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Reducers.ScheduleImmediate.verified.cs @@ -6,10 +6,12 @@ partial class Reducers { private static class __ScheduleScheduleImmediateName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(ScheduleImmediate) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(ScheduleImmediate), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleScheduleImmediateName() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs index 4c7cf63ba0a..77fcaf513d2 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Test.NestingNamespaces.AndClasses.InsertData2.verified.cs @@ -8,10 +8,12 @@ partial class AndClasses { private static class __ScheduleInsertData2Name { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(InsertData2) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(InsertData2), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleInsertData2Name() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.Init.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.Init.verified.cs index 4700a0f58e7..f313a9af2fd 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.Init.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.Init.verified.cs @@ -6,10 +6,12 @@ partial class Timers { private static class __ScheduleInitName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(Init) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(Init), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleInitName() { } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendScheduledMessage.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendScheduledMessage.verified.cs index 679d0ff1e91..f6a1283b596 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendScheduledMessage.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module.net10#Timers.SendScheduledMessage.verified.cs @@ -6,10 +6,12 @@ partial class Timers { private static class __ScheduleSendScheduledMessageName { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName( - "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", - nameof(SendScheduledMessage) - ); + internal static readonly string Name = + global::SpacetimeDB.Internal.Module.ResolveFunctionName( + "server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + nameof(SendScheduledMessage), + null + ); // Prevent eager initialization before the root installs namespace placements. static __ScheduleSendScheduledMessageName() { } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 8c700d47093..d4567d2ea07 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -1820,10 +1820,10 @@ public Scope.Extensions GenerateSchedule() $$""" private static class {{cacheName}} { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName({{SymbolDisplay.FormatLiteral( + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveFunctionName({{SymbolDisplay.FormatLiteral( declaringAssembly, true - )}}, {{functionName}}); + )}}, nameof({{Identifier}}), {{(string.IsNullOrEmpty(CanonicalName) ? "null" : SymbolDisplay.FormatLiteral(CanonicalName!, true))}}); // Prevent eager initialization before the root installs namespace placements. static {{cacheName}}() { } } @@ -2067,10 +2067,10 @@ public Scope.Extensions GenerateSchedule() $$""" private static class {{cacheName}} { - internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveName({{SymbolDisplay.FormatLiteral( + internal static readonly string Name = global::SpacetimeDB.Internal.Module.ResolveFunctionName({{SymbolDisplay.FormatLiteral( declaringAssembly, true - )}}, {{functionName}}); + )}}, nameof({{Identifier}}), {{(string.IsNullOrEmpty(CanonicalName) ? "null" : SymbolDisplay.FormatLiteral(CanonicalName!, true))}}); // Prevent eager initialization before the root installs namespace placements. static {{cacheName}}() { } } @@ -3068,15 +3068,19 @@ void Add(string name, string owner, string declaration) var consumerReadOnlyAccessors = ConsumerAccessors("ReadOnlyTables"); var consumerQueryAccessors = ConsumerAccessors("Queries"); + var declaredCasePolicy = + settings.Array.Length == 1 ? settings.Array[0].CaseConversionPolicy : null; + var rootCasePolicy = declaredCasePolicy ?? "SnakeCase"; + var compositionRegistration = new List { "global::SpacetimeDB.Internal.Module.InstallNamespaces(new global::SpacetimeDB.Internal.NamespaceRegistry(" + SymbolDisplay.FormatLiteral(identity, true) - + ", new global::System.Collections.Generic.KeyValuePair[] {" + + $", global::SpacetimeDB.CaseConversionPolicy.{rootCasePolicy}, new (string, string, string?, global::SpacetimeDB.CaseConversionPolicy)[] {{" + string.Join( ",", mountByIdentity.Values.Select(m => - $"new({SymbolDisplay.FormatLiteral(m.AssemblyIdentity, true)}, {SymbolDisplay.FormatLiteral(m.Accessor, true)})" + $"({SymbolDisplay.FormatLiteral(m.AssemblyIdentity, true)}, {SymbolDisplay.FormatLiteral(m.Accessor, true)}, {(m.Name is { } name ? SymbolDisplay.FormatLiteral(name, true) : "null")}, global::SpacetimeDB.CaseConversionPolicy.{assemblies.Array.Single(a => a.Identity == m.AssemblyIdentity).CaseConversionPolicy ?? "SnakeCase"})" ) ) + "}));", @@ -3096,7 +3100,7 @@ void Add(string name, string owner, string declaration) $"{assembly.DescriptorTypeName}.Register(child{i}, global::SpacetimeDB.Internal.Module.RootBuilder);" ); compositionRegistration.Add( - $"global::SpacetimeDB.Internal.Module.RootBuilder.RegisterSubmodule({SymbolDisplay.FormatLiteral(mountByIdentity[assembly.Identity].Accessor, true)}, child{i});" + $"global::SpacetimeDB.Internal.Module.RootBuilder.RegisterSubmodule({SymbolDisplay.FormatLiteral(mountByIdentity[assembly.Identity].Accessor, true)}, {(mountByIdentity[assembly.Identity].Name is { } name ? SymbolDisplay.FormatLiteral(name, true) : "null")}, child{i});" ); } @@ -3118,11 +3122,8 @@ void Add(string name, string owner, string declaration) ); } - var declaredCasePolicy = - settings.Array.Length == 1 ? settings.Array[0].CaseConversionPolicy : null; // A shared typespace also has one naming policy. Unspecified dependency // settings inherit the root policy, whose host default is SnakeCase. - var rootCasePolicy = declaredCasePolicy ?? "SnakeCase"; foreach (var assembly in publicScopeAssemblies) { if ( diff --git a/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs b/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs index bad9d6b66ee..beaace7d237 100644 --- a/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs +++ b/crates/bindings-csharp/Codegen/NamespaceDeclaration.cs @@ -6,7 +6,7 @@ namespace SpacetimeDB.Codegen; using Microsoft.CodeAnalysis.CSharp; using static Utils; -internal record NamespaceDeclaration(string AssemblyIdentity, string Accessor) +internal record NamespaceDeclaration(string AssemblyIdentity, string Accessor, string? Name) { public string AccessorIdentifier => EscapeIdentifier(Accessor); @@ -96,6 +96,9 @@ tree.Options is CSharpParseOptions options attribute.NamedArguments.FirstOrDefault(static a => a.Key == "Accessor").Value.Value as string ?? ""; + var name = + attribute.NamedArguments.FirstOrDefault(static a => a.Key == "Name").Value.Value + as string; // Keywords are stored unescaped and escaped only when rendering C#. if ( accessor.Length == 0 @@ -115,40 +118,22 @@ as string ); } - // The accessor is also the database namespace, so both sets of rules apply. - // The host remains authoritative for full Unicode identifier validation. - if ( - accessor.Length == 0 - || !(char.IsLetter(accessor[0]) || accessor[0] == '_') - || accessor.Any(static c => !(char.IsLetterOrDigit(c) || c == '_')) - || !accessor.IsNormalized(NormalizationForm.FormC) - ) - { - ReportError( - diag, - attribute, - ref valid, - "Accessor must also be a nonempty database identifier: letters, digits or underscores, starting with a letter or underscore." - ); - } - - if (Encoding.UTF8.GetByteCount(accessor) > 63) + ValidateDatabaseIdentifier(diag, attribute, ref valid, accessor, "Accessor"); + if (name is not null) { - ReportError( - diag, - attribute, - ref valid, - "Namespace names cannot exceed 63 UTF-8 bytes (the current host limit)." - ); - } - - if ( - accessor.Equals("st", StringComparison.OrdinalIgnoreCase) - || accessor.Equals("spacetimedb", StringComparison.OrdinalIgnoreCase) - || accessor.StartsWith("pg_", StringComparison.OrdinalIgnoreCase) - ) - { - ReportError(diag, attribute, ref valid, $"Namespace '{accessor}' is reserved."); + ValidateDatabaseIdentifier(diag, attribute, ref valid, name, "Name"); + if ( + accessor.Equals("public", StringComparison.OrdinalIgnoreCase) + != name.Equals("public", StringComparison.OrdinalIgnoreCase) + ) + { + ReportError( + diag, + attribute, + ref valid, + "The public scope cannot be renamed or targeted by a different accessor." + ); + } } CheckDuplicate( @@ -193,12 +178,53 @@ as string if (valid) { - result.Add(new NamespaceDeclaration(identity, accessor)); + result.Add(new NamespaceDeclaration(identity, accessor, name)); } } return new EquatableArray(result.ToImmutable()); } + private static void ValidateDatabaseIdentifier( + DiagReporter diag, + AttributeData attribute, + ref bool valid, + string value, + string property + ) + { + if ( + value.Length == 0 + || !(char.IsLetter(value[0]) || value[0] == '_') + || value.Any(static c => !(char.IsLetterOrDigit(c) || c == '_')) + || !value.IsNormalized(NormalizationForm.FormC) + ) + { + ReportError( + diag, + attribute, + ref valid, + $"{property} must be a nonempty database identifier: letters, digits or underscores, starting with a letter or underscore." + ); + } + if (Encoding.UTF8.GetByteCount(value) > 63) + { + ReportError( + diag, + attribute, + ref valid, + $"{property} cannot exceed 63 UTF-8 bytes (the current host limit)." + ); + } + if ( + value.Equals("st", StringComparison.OrdinalIgnoreCase) + || value.Equals("spacetimedb", StringComparison.OrdinalIgnoreCase) + || value.StartsWith("pg_", StringComparison.OrdinalIgnoreCase) + ) + { + ReportError(diag, attribute, ref valid, $"Namespace {property} '{value}' is reserved."); + } + } + private static void ReportError( DiagReporter diag, AttributeData attribute, diff --git a/crates/bindings-csharp/README.md b/crates/bindings-csharp/README.md index da9368fe809..bfbe4bf6d85 100644 --- a/crates/bindings-csharp/README.md +++ b/crates/bindings-csharp/README.md @@ -34,7 +34,7 @@ Descriptor-bearing dependencies, including transitive dependencies, register automatically once in `public` unless the root assigns a namespace: ```csharp -[assembly: SpacetimeDB.Namespace(typeof(AuthLib.Marker), Accessor = "MyAuth")] +[assembly: SpacetimeDB.Namespace(typeof(AuthLib.Marker), Accessor = "MyAuth", Name = "auth_data")] ``` The marker can be any accessible type declared in the dependency assembly. @@ -48,6 +48,14 @@ AuthLib helpers continue to use `ctx.Db.User` and `ctx.From.User()`, regardless of the namespace selected by the root. Ordinary helper calls share the caller's context and transaction; a namespace is not a security boundary between helpers. +`Accessor` controls the C# member name; `Name` controls the database namespace. +For this example, raw SQL uses `auth_data.auth_users`, while generated clients +use `conn.Db.MyAuth.User` and `q.From.MyAuth.User()`. Generated client queries and +network calls use the canonical database names automatically. +When `Name` is omitted, the host applies the root module's case-conversion policy +to the accessor: with the default `SnakeCase` policy, `MyAuth` becomes `my_auth`. +An explicit `Name` is used as supplied, without case conversion. + #### Restrictions and limitations - Only the consuming root chooses namespace placement. A dependency that itself @@ -59,16 +67,18 @@ context and transaction; a namespace is not a security boundary between helpers. - Dependencies in `public` inherit the root's case-conversion policy (`SnakeCase` by default). An explicitly different policy is a compilation error. Mount the dependency in a named namespace to keep its independent naming policy. -- `Accessor` is currently both the C# accessor and database namespace. There is - no separate SQL-level `Name`. It must be a valid C# and database identifier, - at most 63 UTF-8 bytes. Names are checked for case-insensitive duplicates; +- `Accessor` must be a valid C# and database identifier; optional `Name` must be + a valid database identifier. Both are limited to 63 UTF-8 bytes. + Accessors are checked for case-insensitive duplicates; the host validates + canonical namespace collisions. `st`, `spacetimedb`, and names starting with `pg_` are reserved. Keywords use their plain spelling in the attribute and `@` in C# expressions. + The `public` scope cannot be renamed or targeted through a different accessor. - Named namespaces cannot declare lifecycle reducers, nonempty environment schemas, or RLS filters. The generator rejects these when composing the root. They remain valid when the dependency is published alone or registered in `public`, subject to ordinary host validation (including lifecycle uniqueness). -- Define RLS in the root, using qualified table names, as in +- Define RLS in the root, using canonical qualified table names, as in [the integration fixture](../../modules/namespace-test-cs/Lib.cs). Library-defined RLS in a named namespace is unsupported; it must not be relied on to protect data. diff --git a/crates/bindings-csharp/Runtime/Attrs.cs b/crates/bindings-csharp/Runtime/Attrs.cs index 2c8e53a8af0..f6dcda8533f 100644 --- a/crates/bindings-csharp/Runtime/Attrs.cs +++ b/crates/bindings-csharp/Runtime/Attrs.cs @@ -252,8 +252,14 @@ public sealed class NamespaceAttribute(System.Type marker) : Attribute { public System.Type Marker { get; } = marker; - /// The C# member name and database namespace used for the mounted module. + /// The C# member name used for the mounted module. public string Accessor { get; set; } = ""; + + /// + /// The database namespace. When omitted, the host applies the parent module's + /// case conversion policy to Accessor. + /// + public string? Name { get; set; } } #endif } diff --git a/crates/bindings-csharp/Runtime/Internal/CanonicalName.cs b/crates/bindings-csharp/Runtime/Internal/CanonicalName.cs new file mode 100644 index 00000000000..fb1e859b884 --- /dev/null +++ b/crates/bindings-csharp/Runtime/Internal/CanonicalName.cs @@ -0,0 +1,169 @@ +namespace SpacetimeDB.Internal; + +using System.Globalization; +using System.Text; + +internal static class CanonicalName +{ + internal static string Convert(string source, CaseConversionPolicy policy) + { + if (policy == CaseConversionPolicy.None) + { + return source; + } + + // Match the host's convert_case 0.6 default word boundaries. This runs only + // when installing mounts or initializing an immediate-scheduling name cache. + var elements = new List(); + var iterator = StringInfo.GetTextElementEnumerator(source); + while (iterator.MoveNext()) + { + elements.Add(iterator.GetTextElement()); + } + var result = new StringBuilder(); + var word = new StringBuilder(); + for (var i = 0; i <= elements.Count; i++) + { + var current = i < elements.Count ? elements[i] : ""; + var separator = current is "" or "_" or "-" or " "; + var previous = i > 0 ? elements[i - 1] : ""; + var next = i + 1 < elements.Count ? elements[i + 1] : ""; + var boundary = + separator + || (IsLower(previous) && IsUpper(current)) + || (IsDigit(previous) && (IsLower(current) || IsUpper(current))) + || ((IsLower(previous) || IsUpper(previous)) && IsDigit(current)) + || (IsUpper(previous) && IsUpper(current) && IsLower(next)); + if (boundary && word.Length > 0) + { + if (result.Length > 0) + { + result.Append('_'); + } + AppendLowercase(result, word.ToString()); + word.Clear(); + } + if (!separator) + { + word.Append(current); + } + } + return result.ToString(); + } + + private static bool IsDigit(string value) => + value.Length > 0 && value.All(c => c is >= '0' and <= '9'); + + // These comparisons classify graphemes; a case-insensitive comparison would erase + // the distinction needed by the word-boundary rules. +#pragma warning disable CA1862 + private static bool IsUpper(string value) => + (value.ToUpperInvariant() != value.ToLowerInvariant() || value.Contains('\u0130')) + && value == value.ToUpperInvariant() + && !value.EnumerateRunes().Any(HasUppercaseExpansion); + + private static bool IsLower(string value) => + ( + value.ToUpperInvariant() != value.ToLowerInvariant() + || value.EnumerateRunes().Any(HasUppercaseExpansion) + ) + && value == value.ToLowerInvariant() + && !value.Contains('\u0130'); +#pragma warning restore CA1862 + + // Unicode unconditional full-uppercase expansions used by Rust's string casing. + // .NET simple casing leaves some of these unchanged, affecting word boundaries. + private static bool HasUppercaseExpansion(Rune rune) => + rune.Value + is 0x00DF + or 0x0149 + or 0x01F0 + or 0x0390 + or 0x03B0 + or 0x0587 + or >= 0x1E96 + and <= 0x1E9A + or 0x1F50 + or 0x1F52 + or 0x1F54 + or 0x1F56 + or >= 0x1F80 + and <= 0x1FAF + or >= 0x1FB2 + and <= 0x1FB4 + or >= 0x1FB6 + and <= 0x1FB7 + or 0x1FBC + or >= 0x1FC2 + and <= 0x1FC4 + or >= 0x1FC6 + and <= 0x1FC7 + or 0x1FCC + or >= 0x1FD2 + and <= 0x1FD3 + or >= 0x1FD6 + and <= 0x1FD7 + or >= 0x1FE2 + and <= 0x1FE4 + or >= 0x1FE6 + and <= 0x1FE7 + or >= 0x1FF2 + and <= 0x1FF4 + or >= 0x1FF6 + and <= 0x1FF7 + or 0x1FFC + or >= 0xFB00 + and <= 0xFB06 + or >= 0xFB13 + and <= 0xFB17; + + private static void AppendLowercase(StringBuilder result, string word) + { + var runes = word.EnumerateRunes().ToArray(); + for (var i = 0; i < runes.Length; i++) + { + // Rust uses Unicode full lowercase mappings; .NET's invariant mapping + // is simple and omits dotted-I expansion and contextual final sigma. + if (runes[i].Value == 0x0130) + { + result.Append("i\u0307"); + } + else if ( + runes[i].Value == 0x03A3 + && HasCasedRune(runes, i, -1) + && !HasCasedRune(runes, i, 1) + ) + { + result.Append('\u03C2'); + } + else + { + result.Append(Rune.ToLowerInvariant(runes[i]).ToString()); + } + } + } + + private static bool HasCasedRune(Rune[] runes, int index, int direction) + { + for (var i = index + direction; i >= 0 && i < runes.Length; i += direction) + { + var category = Rune.GetUnicodeCategory(runes[i]); + if ( + category + is UnicodeCategory.NonSpacingMark + or UnicodeCategory.EnclosingMark + or UnicodeCategory.Format + or UnicodeCategory.ModifierLetter + or UnicodeCategory.ModifierSymbol + ) + { + continue; + } + return Rune.ToUpperInvariant(runes[i]) != Rune.ToLowerInvariant(runes[i]) + || HasUppercaseExpansion(runes[i]) + || runes[i].Value == 0x0130 + || category == UnicodeCategory.TitlecaseLetter; + } + return false; + } +} diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index a9a5794b86b..67eaa5180eb 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -61,6 +61,16 @@ public static string ResolveName(string assemblyIdentity, string localName) => ?? throw new InvalidOperationException("Module namespaces have not been installed.") ).Resolve(assemblyIdentity, localName); + public static string ResolveFunctionName( + string assemblyIdentity, + string sourceName, + string? explicitName + ) => + ( + namespaces + ?? throw new InvalidOperationException("Module namespaces have not been installed.") + ).ResolveFunction(assemblyIdentity, sourceName, explicitName); + public static SqlTableName ResolveSqlName(string assemblyIdentity, string localName) => ( namespaces diff --git a/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs b/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs index 7a6dd4c3c40..6be3adf4669 100644 --- a/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs +++ b/crates/bindings-csharp/Runtime/Internal/ModuleBuilder.cs @@ -73,8 +73,14 @@ private static RawScopedTypeNameV10 MakeScopedTypeName(Type type) => internal void RegisterSubmodule(RawSubmoduleV10 submodule) => submoduleDefs.Add(submodule); - public void RegisterSubmodule(string name, ModuleBuilder child) => - RegisterSubmodule(new RawSubmoduleV10(name, child.BuildModuleDefinition())); + public void RegisterSubmodule(string accessor, string? name, ModuleBuilder child) + { + RegisterSubmodule(new RawSubmoduleV10(accessor, child.BuildModuleDefinition())); + if (name is not null) + { + explicitNames.Add(new ExplicitNameEntry.Namespace(new NameMapping(accessor, name))); + } + } // Receives types to store the reference in the dictionary so that we can resolve it later and to avoid infinite recursion inside `makeType`. internal AlgebraicType.Ref RegisterType( diff --git a/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs b/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs index f3aa2019fc0..3b35500cc76 100644 --- a/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs +++ b/crates/bindings-csharp/Runtime/Internal/NamespaceRegistry.cs @@ -3,21 +3,44 @@ namespace SpacetimeDB.Internal; /// Immutable assembly placement installed before module registration. public sealed class NamespaceRegistry { - private readonly Dictionary mounts = new(StringComparer.Ordinal); + private readonly Dictionary< + string, + (string Accessor, string Canonical, CaseConversionPolicy Policy) + > mounts = new(StringComparer.Ordinal); + private readonly CaseConversionPolicy rootPolicy; - public NamespaceRegistry(string rootIdentity, IEnumerable> mounts) + public NamespaceRegistry( + string rootIdentity, + CaseConversionPolicy rootPolicy, + IEnumerable<( + string AssemblyIdentity, + string Accessor, + string? Name, + CaseConversionPolicy Policy + )> mounts + ) { + this.rootPolicy = rootPolicy; foreach (var mount in mounts) { - if (mount.Key == rootIdentity) + if (mount.AssemblyIdentity == rootIdentity) { throw new ArgumentException("The root assembly cannot be mounted.", nameof(mounts)); } - if (!this.mounts.TryAdd(mount.Key, mount.Value)) + if ( + !this.mounts.TryAdd( + mount.AssemblyIdentity, + ( + mount.Accessor, + mount.Name ?? CanonicalName.Convert(mount.Accessor, rootPolicy), + mount.Policy + ) + ) + ) { throw new ArgumentException( - $"Assembly '{mount.Key}' is mounted more than once.", + $"Assembly '{mount.AssemblyIdentity}' is mounted more than once.", nameof(mounts) ); } @@ -25,11 +48,25 @@ public NamespaceRegistry(string rootIdentity, IEnumerable - mounts.TryGetValue(assemblyIdentity, out var name) - && !name.Equals("public", StringComparison.OrdinalIgnoreCase) - ? name + mounts.TryGetValue(assemblyIdentity, out var mount) + && !mount.Accessor.Equals("public", StringComparison.OrdinalIgnoreCase) + ? mount.Accessor : null; + public string ResolveFunction(string assemblyIdentity, string sourceName, string? explicitName) + { + if ( + mounts.TryGetValue(assemblyIdentity, out var mount) + && !mount.Accessor.Equals("public", StringComparison.OrdinalIgnoreCase) + ) + { + return mount.Canonical + + "." + + (explicitName ?? CanonicalName.Convert(sourceName, mount.Policy)); + } + return explicitName ?? CanonicalName.Convert(sourceName, rootPolicy); + } + public string Resolve(string assemblyIdentity, string localName) => ResolveNamespace(assemblyIdentity) is { } name ? name + "." + localName : localName; diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs index 054e0b43a95..e01c48cf7bc 100644 --- a/crates/codegen/src/csharp.rs +++ b/crates/codegen/src/csharp.rs @@ -506,84 +506,82 @@ pub struct Csharp<'opts> { impl Lang for Csharp<'_> { fn generate_table_file_from_schema(&self, module: &ModuleDef, table: &TableDef, schema: TableSchema) -> OutputFile { - self.scope(NamespacePath::root()) + self.scope(module) .generate_table_file_from_schema(module, table, schema) } fn generate_type_files(&self, module: &ModuleDef, typ: &TypeDef) -> Vec { - self.scope(NamespacePath::root()).generate_type_files(module, typ) + self.scope(module).generate_type_files(module, typ) } fn generate_reducer_file(&self, module: &ModuleDef, reducer: &ReducerDef) -> OutputFile { - self.scope(NamespacePath::root()).generate_reducer_file(module, reducer) + self.scope(module).generate_reducer_file(module, reducer) } fn generate_procedure_file(&self, module: &ModuleDef, procedure: &ProcedureDef) -> OutputFile { - self.scope(NamespacePath::root()) - .generate_procedure_file(module, procedure) + self.scope(module).generate_procedure_file(module, procedure) } - fn generate_submodule_table_file(&self, module: &ModuleDef, path: &NamespacePath, table: &TableDef) -> OutputFile { - scoped_file(path, self.scope(path.clone()).generate_table_file(module, table)) + fn generate_submodule_table_file(&self, module: &ModuleDef, table: &TableDef) -> OutputFile { + scoped_file( + module.accessor_path(), + self.scope(module).generate_table_file(module, table), + ) } - fn generate_submodule_view_file(&self, module: &ModuleDef, path: &NamespacePath, view: &ViewDef) -> OutputFile { - scoped_file(path, self.scope(path.clone()).generate_view_file(module, view)) + fn generate_submodule_view_file(&self, module: &ModuleDef, view: &ViewDef) -> OutputFile { + scoped_file( + module.accessor_path(), + self.scope(module).generate_view_file(module, view), + ) } - fn generate_submodule_reducer_file( - &self, - module: &ModuleDef, - path: &NamespacePath, - reducer: &ReducerDef, - ) -> OutputFile { - scoped_file(path, self.scope(path.clone()).generate_reducer_file(module, reducer)) + fn generate_submodule_reducer_file(&self, module: &ModuleDef, reducer: &ReducerDef) -> OutputFile { + scoped_file( + module.accessor_path(), + self.scope(module).generate_reducer_file(module, reducer), + ) } - fn generate_submodule_procedure_file( - &self, - module: &ModuleDef, - path: &NamespacePath, - procedure: &ProcedureDef, - ) -> OutputFile { + fn generate_submodule_procedure_file(&self, module: &ModuleDef, procedure: &ProcedureDef) -> OutputFile { scoped_file( - path, - self.scope(path.clone()).generate_procedure_file(module, procedure), + module.accessor_path(), + self.scope(module).generate_procedure_file(module, procedure), ) } fn generate_global_files(&self, module: &ModuleDef, options: &CodegenOptions) -> Vec { - let mut files = self.scope(NamespacePath::root()).generate_global_files(module, options); - self.child_files(module, &NamespacePath::root(), &mut files); + let mut files = self.scope(module).generate_global_files(module, options); + self.child_files(module, &mut files); files } } impl Csharp<'_> { - fn scope(&self, path: NamespacePath) -> CsharpScope<'_> { - let namespace = clr_namespace(self.namespace, &path); + fn scope(&self, module: &ModuleDef) -> CsharpScope<'_> { + let namespace = clr_namespace(self.namespace, module.accessor_path()); CsharpScope { namespace, root_namespace: self.namespace, - path, + path: module.path().clone(), } } - fn child_files(&self, module: &ModuleDef, path: &NamespacePath, files: &mut Vec) { - for (name, child) in module.submodules() { - let path = path.child(name.clone()); - let scope = self.scope(path.clone()); + fn child_files(&self, module: &ModuleDef, files: &mut Vec) { + for child in module.submodules().values() { + let path = child.accessor_path(); + let scope = self.scope(child); // Child typespaces are independent, including types used only by functions. for typ in child.types() { files.extend( scope .generate_type_files(child, typ) .into_iter() - .map(|file| scoped_file(&path, file)), + .map(|file| scoped_file(path, file)), ); } - files.push(scoped_file(&path, scope.child_globals(child))); - self.child_files(child, &path, files); + files.push(scoped_file(path, scope.child_globals(child))); + self.child_files(child, files); } } } @@ -591,6 +589,7 @@ impl Csharp<'_> { struct CsharpScope<'a> { namespace: String, root_namespace: &'a str, + // Canonical database path, never a C# member or CLR namespace path. path: NamespacePath, } @@ -633,8 +632,9 @@ impl CsharpScope<'_> { } fn child_members(&self, output: &mut CodeIndenter, module: &ModuleDef, container: &str) { - for name in module.submodules().keys() { - let namespace = clr_namespace(self.root_namespace, &self.path.child(name.clone())); + for child in module.submodules().values() { + let name = child.mount_accessor_name().unwrap(); + let namespace = clr_namespace(self.root_namespace, child.accessor_path()); if container == "From" { writeln!(output, "public global::{namespace}.From @{name} {{ get; }} = new();"); } else { @@ -653,7 +653,8 @@ impl CsharpScope<'_> { } else { writeln!(output, "internal {container}({conn} conn) : base(conn)"); indented_block(output, |output| { - for name in module.submodules().keys() { + for child in module.submodules().values() { + let name = child.mount_accessor_name().unwrap(); writeln!(output, "@{name} = new(conn);"); if container == "RemoteReducers" { writeln!(output, "@{name}.InternalOnUnhandledReducerError += (ctx, error) => InternalOnUnhandledReducerError?.Invoke(ctx, error);"); @@ -720,7 +721,8 @@ impl CsharpScope<'_> { accessor.deref().to_case(Case::Pascal) ); } - for name in module.submodules().keys() { + for child in module.submodules().values() { + let name = child.mount_accessor_name().unwrap(); writeln!(output, "@{name} = new(conn, register);"); } }); @@ -1325,7 +1327,8 @@ impl Lang for CsharpScope<'_> { accessor_name.deref().to_case(Case::Pascal) ); } - for name in module.submodules().keys() { + for child in module.submodules().values() { + let name = child.mount_accessor_name().unwrap(); writeln!(output, "@{name} = new(conn, AddTable);"); } }); @@ -1348,17 +1351,17 @@ impl Lang for CsharpScope<'_> { child_tables.sort_by(|(a_path, _, a), (b_path, _, b)| { (a_path, &a.accessor_name).cmp(&(b_path, &b.accessor_name)) }); - for (path, _, table) in child_tables.into_iter().filter(|(path, _, table)| { + for (_, owner, table) in child_tables.into_iter().filter(|(path, _, table)| { !path.is_empty() && table.table_access == spacetimedb_lib::db::raw_def::v9::TableAccess::Public }) { writeln!( output, "new QueryBuilder().From.{}{}().ToSql(),", - member_path(&path), + member_path(owner.accessor_path()), table.accessor_name.deref().to_case(Case::Pascal) ); } - for (path, _, view) in module + for (_, owner, view) in module .all_views_with_prefix() .into_iter() .filter(|(path, _, _)| !path.is_empty()) @@ -1366,7 +1369,7 @@ impl Lang for CsharpScope<'_> { writeln!( output, "new QueryBuilder().From.{}{}().ToSql(),", - member_path(&path), + member_path(owner.accessor_path()), view.accessor_name.deref().to_case(Case::Pascal) ); } @@ -1520,13 +1523,13 @@ impl Lang for CsharpScope<'_> { "Reducer.{reducer_name} args => Reducers.Invoke{reducer_name}(eventContext, args)," ); } - for (path, _, reducer) in module + for (_, owner, reducer) in module .all_reducers_with_prefix() .into_iter() .filter(|(path, _, reducer)| !path.is_empty() && !reducer.visibility.is_private()) { - let namespace = clr_namespace(self.root_namespace, &path); - let member = member_path(&path); + let namespace = clr_namespace(self.root_namespace, owner.accessor_path()); + let member = member_path(owner.accessor_path()); let name = reducer.accessor_name.deref().to_case(Case::Pascal); writeln!(output, "global::{namespace}.Reducer.{name} args => Reducers.{member}Invoke{name}(eventContext, args),"); } diff --git a/crates/codegen/tests/codegen.rs b/crates/codegen/tests/codegen.rs index dcad47009a7..699f1dac7bf 100644 --- a/crates/codegen/tests/codegen.rs +++ b/crates/codegen/tests/codegen.rs @@ -143,8 +143,12 @@ fn csharp_client_for_typescript_submodule_compiles_and_runs() { r#"class Program { static void Main() { var conn = new SpacetimeDB.DbConnection(); try { - if (conn.Db.lib.LibData.RemoteTableName != "lib.libData") throw new System.Exception(conn.Db.lib.LibData.RemoteTableName); - if (((SpacetimeDB.IReducerArgs)new SpacetimeDB.lib.Reducer.LibInsert("value")).ReducerName != "lib.lib_insert") throw new System.Exception("wrong reducer name"); + if (conn.Db.myLib.LibData.RemoteTableName != "my_lib.libData") throw new System.Exception(conn.Db.myLib.LibData.RemoteTableName); + if (((SpacetimeDB.IReducerArgs)new SpacetimeDB.myLib.Reducer.LibInsert("value")).ReducerName != "my_lib.lib_insert") throw new System.Exception("wrong reducer name"); + if (((SpacetimeDB.IProcedureArgs)new SpacetimeDB.myLib.Procedure.LibCountArgs()).ProcedureName != "my_lib.lib_count") throw new System.Exception("wrong procedure name"); + var sql = new SpacetimeDB.QueryBuilder().From.myLib.LibData().ToSql(); + if (!sql.Contains("\"my_lib\".\"libData\"") || sql.Contains("myLib")) throw new System.Exception(sql); + if (!System.Linq.Enumerable.Contains(SpacetimeDB.QueryBuilder.AllTablesSqlQueries(), sql)) throw new System.Exception("missing namespace subscription"); } finally { conn.Disconnect(); } } }"#, ); diff --git a/crates/testing/tests/environment.rs b/crates/testing/tests/environment.rs index eca89fc3892..b83e0b5f2cc 100644 --- a/crates/testing/tests/environment.rs +++ b/crates/testing/tests/environment.rs @@ -83,14 +83,15 @@ const TYPESCRIPT_SCOPE: SubmoduleScopeCases = SubmoduleScopeCases { }; const CSHARP_SCOPE: SubmoduleScopeCases = SubmoduleScopeCases { - reducer: "MyAuth.expect_environment", - procedures: &["MyAuth.read_environment", "MyAuth.read_environment_in_tx"], + // The fixture omits Name: the root's default policy converts MyAuth to my_auth. + reducer: "my_auth.expect_environment", + procedures: &["my_auth.read_environment", "my_auth.read_environment_in_tx"], // C# covers both view context types. The raw-SQL bypass cases above remain TS-only. views: &[ - ("MyAuth.environment_value", "\"MyAuth\".environment_value"), + ("my_auth.environment_value", "my_auth.environment_value"), ( - "MyAuth.anonymous_environment_value", - "\"MyAuth\".anonymous_environment_value", + "my_auth.anonymous_environment_value", + "my_auth.anonymous_environment_value", ), ], root_http_routes: &["/root-environment", "/auth-environment"], diff --git a/crates/testing/tests/standalone_integration_test.rs b/crates/testing/tests/standalone_integration_test.rs index 7b7d452d454..3dde72f5479 100644 --- a/crates/testing/tests/standalone_integration_test.rs +++ b/crates/testing/tests/standalone_integration_test.rs @@ -174,6 +174,75 @@ fn namespace_csharp_cross_namespace_calls() { ); } +#[test] +#[serial] +fn namespace_csharp_canonical_name_resolution() { + use spacetimedb_lib::db::raw_def::v10::{CaseConversionPolicy, ExplicitNames, RawModuleDefV10Builder}; + use spacetimedb_schema::def::ModuleDef; + init(); + CompiledModule::compile("namespace-test-cs", CompilationMode::Debug).with_module_async( + DEFAULT_CONFIG, + |module| async move { + // Derive expected names with the actual host validator, not a second test-side converter. + for accessor in ["MyHTTP2Auth", "public", ""] { + for root_none in [false, true] { + for child_none in [false, true] { + for (source, explicit) in [ + ("HTTP2ReducerTick", None), + ("__my__XMLParser99", None), + ("already_snake_case", None), + ("SourceName", Some("ExplicitNAME")), + ] { + let mut root = RawModuleDefV10Builder::new(); + root.set_case_conversion_policy(if root_none { + CaseConversionPolicy::None + } else { + CaseConversionPolicy::SnakeCase + }); + let mut child = RawModuleDefV10Builder::new(); + child.set_case_conversion_policy(if child_none { + CaseConversionPolicy::None + } else { + CaseConversionPolicy::SnakeCase + }); + let named = !accessor.is_empty() && accessor != "public"; + let target = if named { &mut child } else { &mut root }; + target.add_reducer(source, spacetimedb_lib::ProductType::unit()); + if let Some(name) = explicit { + let mut names = ExplicitNames::default(); + names.insert_function(source, name); + target.add_explicit_names(names); + } + if named { + root.add_submodule(accessor, child.finish()); + } + let schema: ModuleDef = root.finish().try_into().unwrap(); + let expected = schema.all_reducers_with_prefix()[0].2.name.to_string(); + let args = serde_json::json!([ + accessor, + null, + source, + explicit.map(|name| serde_json::json!({"some": name})), + root_none, + child_none + ]) + .to_string(); + assert_eq!( + module + .call_procedure_with_args("resolve_schedule_name", &args) + .await + .unwrap(), + AlgebraicValue::String(expected.into()), + "{args}" + ); + } + } + } + } + }, + ); +} + #[test] #[serial] fn test_calling_a_reducer_typescript() { diff --git a/modules/namespace-test-cs/Lib.cs b/modules/namespace-test-cs/Lib.cs index 73a8938dc80..76d771f4cf7 100644 --- a/modules/namespace-test-cs/Lib.cs +++ b/modules/namespace-test-cs/Lib.cs @@ -1,6 +1,6 @@ using SpacetimeDB; -[assembly: Namespace(typeof(AuthLib.Marker), Accessor = "MyAuth")] +[assembly: Namespace(typeof(AuthLib.Marker), Accessor = "MyAuth", Name = "auth_data")] [assembly: Namespace(typeof(AuditLib.Marker), Accessor = "class")] namespace NamespaceRoot; @@ -20,6 +20,34 @@ public partial struct AuthSummary public static partial class Functions { + // Compare the runtime resolver with host validation, including naming policies + // that differ from this fixture's own policy, without publishing extra modules. + [Procedure] + public static string ResolveScheduleName( + ProcedureContext ctx, + string accessor, + string? namespaceName, + string sourceName, + string? functionName, + bool rootNone, + bool childNone + ) => + new SpacetimeDB.Internal.NamespaceRegistry( + "root", + rootNone ? CaseConversionPolicy.None : CaseConversionPolicy.SnakeCase, + accessor.Length == 0 + ? [] + : + [ + ( + "dependency", + accessor, + namespaceName, + childNone ? CaseConversionPolicy.None : CaseConversionPolicy.SnakeCase + ), + ] + ).ResolveFunction(accessor.Length == 0 ? "root" : "dependency", sourceName, functionName); + [Reducer] public static void AddAuthUser(ReducerContext ctx, uint id) { @@ -41,7 +69,7 @@ public static Router Routes() => #pragma warning disable STDB_UNSTABLE [ClientVisibilityFilter] public static readonly Filter ProtectedRows = new Filter.Sql( - "SELECT * FROM \"MyAuth\".protected_row WHERE owner = :sender" + "SELECT * FROM auth_data.protected_row WHERE owner = :sender" ); #pragma warning restore STDB_UNSTABLE diff --git a/sdks/csharp/DEVELOP.md b/sdks/csharp/DEVELOP.md index ba1f78c529d..71a27a4e530 100644 --- a/sdks/csharp/DEVELOP.md +++ b/sdks/csharp/DEVELOP.md @@ -50,16 +50,18 @@ The most important generated types are `RemoteTables` -- also known as the **cli ### Namespace bindings -Suppose a dependency is mounted in the database namespace `MyAuth`, using -`Accessor = "MyAuth"`. Generated C# clients expose its tables through +Suppose a dependency is mounted with `Accessor = "MyAuth", Name = "auth_data"`. +Generated C# clients expose its tables through `conn.Db.MyAuth`, reducers through `conn.Reducers.MyAuth`, procedures through `conn.Procedures.MyAuth`, and query factories through `q.From.MyAuth`. -The mount accessor is also the database namespace; its spelling is preserved. +Generated SQL and network messages use the database namespace `auth_data`. +The C# accessor remains `MyAuth`. When `Name` is omitted, the host derives the +database namespace from the accessor using the root module's case policy. The `--namespace` option of `spacetime generate` controls where generated C# classes are declared; it does not name or rename database namespaces. With `--namespace Game.Bindings`, a root `User` row becomes `Game.Bindings.User`, -while a `User` row in the `MyAuth` database namespace becomes +while a `User` row in that dependency becomes `Game.Bindings.MyAuth.User`. Their table handles remain `conn.Db.User` and `conn.Db.MyAuth.User`, respectively. diff --git a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs index aa50be90ba1..a3ea26bee9f 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/Program.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/Program.cs @@ -96,9 +96,14 @@ void EmptyCache() { Wait(() => connected, "connect"); Require( - conn.Db.MyAuth.User.RemoteTableName == "MyAuth.auth_users", + conn.Db.MyAuth.User.RemoteTableName == "auth_data.auth_users", "Explicit table wire name" ); + Require( + new QueryBuilder().From.MyAuth.User().ToSql() + == "SELECT * FROM \"auth_data\".\"auth_users\"", + "Accessor query must use the canonical namespace and table name" + ); Require( conn.Db.@class.User.RemoteTableName == "class.user", "Keyword namespace wire name" @@ -295,7 +300,7 @@ void EmptyCache() conn.SubscriptionBuilder() .OnApplied(_ => throw new Exception("A non-owner subscribed to private child data")) .OnError((_, _) => privateDenied = true) - .Subscribe(new[] { "SELECT * FROM \"MyAuth\".secret" }); + .Subscribe(new[] { "SELECT * FROM \"auth_data\".secret" }); Wait(() => privateDenied, "private child subscription rejection"); var failed = false; diff --git a/sdks/csharp/examples~/regression-tests/namespaces/README.md b/sdks/csharp/examples~/regression-tests/namespaces/README.md index 236837fd125..682bb271d2c 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/README.md +++ b/sdks/csharp/examples~/regression-tests/namespaces/README.md @@ -2,8 +2,10 @@ Runs generated clients against the .NET 10 module in `modules/namespace-test-cs`. The .NET 8 run verifies backward compatibility; -the .NET 10 run verifies the newer client runtime. Both retain C# 9 to enforce the -generated-code language baseline. It uses `Accessor` as the namespace name throughout. +the .NET 10 run verifies the newer client runtime. +Both retain C# 9 to enforce the generated-code language baseline. +The Auth dependency uses `Accessor = "MyAuth"` and `Name = "auth_data"`: +C# expressions use `MyAuth`, while generated SQL and wire names use `auth_data`. The existing `sdks/csharp/tools~/run-regression-tests.sh 10` harness generates the bindings and runs this client on both frameworks, clearing and republishing the @@ -30,7 +32,8 @@ Coverage: - Root and two mounted libraries with different row types named `User`, plus a dependency automatically registered in `public`, without a namespace declaration. -- Explicit table names and a C# keyword namespace accessor. +- Distinct namespace accessor and canonical name, explicit table names, and a C# + keyword namespace accessor. - Typed subscriptions, filtered queries, both semijoin directions, and overlapping subscriptions without duplicate rows or premature cache removal. - Cross-library helper writes and callbacks observing the complete transaction. diff --git a/sdks/csharp/examples~/regression-tests/namespaces/RootRlsTests.cs b/sdks/csharp/examples~/regression-tests/namespaces/RootRlsTests.cs index 7fa657e8fec..a4b34762546 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/RootRlsTests.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/RootRlsTests.cs @@ -122,7 +122,7 @@ void Write(uint id, Identity owner, uint value) .SubscriptionBuilder() .OnApplied(_ => applied++) .OnError((_, e) => error = e) - .Subscribe(new[] { "SELECT * FROM \"MyAuth\".protected_row" }); + .Subscribe(new[] { "SELECT * FROM \"auth_data\".protected_row" }); Wait(() => applied == 2, "initial subscriptions"); Require(first.Db.MyAuth.ProtectedRow.Iter().Single().Id == 1, "First initial RLS rows"); Require( diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/CountUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/CountUsers.g.cs index 13beb94d9c6..e3ada1d67ef 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/CountUsers.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/CountUsers.g.cs @@ -57,7 +57,7 @@ public CountUsers() [DataContract] public sealed partial class CountUsersArgs : Procedure, IProcedureArgs { - string IProcedureArgs.ProcedureName => "MyAuth.count_users"; + string IProcedureArgs.ProcedureName => "auth_data.count_users"; } } diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadScore.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadScore.g.cs index d04f0c2dce2..aebc61b06a1 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadScore.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Procedures/ReadScore.g.cs @@ -69,7 +69,7 @@ public ReadScoreArgs() { } - string IProcedureArgs.ProcedureName => "MyAuth.read_score"; + string IProcedureArgs.ProcedureName => "auth_data.read_score"; } } diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Add.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Add.g.cs index 5cd8f874e95..5293f88722c 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Add.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Add.g.cs @@ -60,7 +60,7 @@ public Add() { } - string IReducerArgs.ReducerName => "MyAuth.add"; + string IReducerArgs.ReducerName => "auth_data.add"; } } } diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/CancelSchedules.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/CancelSchedules.g.cs index 93ac858ad16..f822ebdef81 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/CancelSchedules.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/CancelSchedules.g.cs @@ -47,7 +47,7 @@ public abstract partial class Reducer [DataContract] public sealed partial class CancelSchedules : global::SpacetimeDB.Types.Reducer, IReducerArgs { - string IReducerArgs.ReducerName => "MyAuth.cancel_schedules"; + string IReducerArgs.ReducerName => "auth_data.cancel_schedules"; } } } diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Fail.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Fail.g.cs index 23b574b280f..0186f95ab00 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Fail.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Fail.g.cs @@ -60,7 +60,7 @@ public Fail() { } - string IReducerArgs.ReducerName => "MyAuth.fail"; + string IReducerArgs.ReducerName => "auth_data.fail"; } } } diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Remove.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Remove.g.cs index c8b74b56fe0..a8f91cc77c7 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Remove.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Remove.g.cs @@ -60,7 +60,7 @@ public Remove() { } - string IReducerArgs.ReducerName => "MyAuth.remove"; + string IReducerArgs.ReducerName => "auth_data.remove"; } } } diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/StartSchedules.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/StartSchedules.g.cs index 6735514356e..8c23799360d 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/StartSchedules.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/StartSchedules.g.cs @@ -47,7 +47,7 @@ public abstract partial class Reducer [DataContract] public sealed partial class StartSchedules : global::SpacetimeDB.Types.Reducer, IReducerArgs { - string IReducerArgs.ReducerName => "MyAuth.start_schedules"; + string IReducerArgs.ReducerName => "auth_data.start_schedules"; } } } diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Update.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Update.g.cs index 9ad92e8c57b..f8903ce2ecb 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Update.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Reducers/Update.g.cs @@ -67,7 +67,7 @@ public Update() { } - string IReducerArgs.ReducerName => "MyAuth.update"; + string IReducerArgs.ReducerName => "auth_data.update"; } } } diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs index 89e143f18bf..fb44c4570e5 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/AnonymousUsers.g.cs @@ -15,8 +15,8 @@ public sealed partial class RemoteTables { public sealed class AnonymousUsersHandle : RemoteTableHandle { - public override string RemoteTableName => "MyAuth.anonymous_users"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "anonymous_users"); + public override string RemoteTableName => "auth_data.anonymous_users"; + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("auth_data", "anonymous_users"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; internal AnonymousUsersHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs index 450b3c5b841..0186e9a7f96 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Notice.g.cs @@ -15,8 +15,8 @@ public sealed partial class RemoteTables { public sealed class NoticeHandle : RemoteEventTableHandle { - public override string RemoteTableName => "MyAuth.notice"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "notice"); + public override string RemoteTableName => "auth_data.notice"; + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("auth_data", "notice"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; internal NoticeHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs index afd6b5330e9..fc369d56d87 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ProtectedRow.g.cs @@ -15,8 +15,8 @@ public sealed partial class RemoteTables { public sealed class ProtectedRowHandle : RemoteTableHandle { - public override string RemoteTableName => "MyAuth.protected_row"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "protected_row"); + public override string RemoteTableName => "auth_data.protected_row"; + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("auth_data", "protected_row"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class IdUniqueIndex : UniqueIndexBase diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs index 6c9d5029d5a..5566d2533c5 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/QueryUsers.g.cs @@ -15,8 +15,8 @@ public sealed partial class RemoteTables { public sealed class QueryUsersHandle : RemoteTableHandle { - public override string RemoteTableName => "MyAuth.query_users"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "query_users"); + public override string RemoteTableName => "auth_data.query_users"; + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("auth_data", "query_users"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class IdUniqueIndex : UniqueIndexBase diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs index a3b1e3ead3b..a468054d64c 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/ScheduleResult.g.cs @@ -15,8 +15,8 @@ public sealed partial class RemoteTables { public sealed class ScheduleResultHandle : RemoteTableHandle { - public override string RemoteTableName => "MyAuth.schedule_result"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "schedule_result"); + public override string RemoteTableName => "auth_data.schedule_result"; + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("auth_data", "schedule_result"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class JobIdUniqueIndex : UniqueIndexBase diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs index e3a0f740b38..b64600d1798 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/User.g.cs @@ -15,8 +15,8 @@ public sealed partial class RemoteTables { public sealed class UserHandle : RemoteTableHandle { - public override string RemoteTableName => "MyAuth.auth_users"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "auth_users"); + public override string RemoteTableName => "auth_data.auth_users"; + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("auth_data", "auth_users"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; public sealed class IdUniqueIndex : UniqueIndexBase diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs index caa835ebd7a..d6dd72eb559 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/MyAuth/Tables/Users.g.cs @@ -15,8 +15,8 @@ public sealed partial class RemoteTables { public sealed class UsersHandle : RemoteTableHandle { - public override string RemoteTableName => "MyAuth.users"; - internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("MyAuth", "users"); + public override string RemoteTableName => "auth_data.users"; + internal static readonly global::SpacetimeDB.SqlTableName SqlName = new global::SpacetimeDB.SqlTableName("auth_data", "users"); protected override global::SpacetimeDB.SqlTableName RemoteSqlTableName => SqlName; internal UsersHandle(global::SpacetimeDB.Types.DbConnection conn) : base(conn) diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/ResolveScheduleName.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/ResolveScheduleName.g.cs new file mode 100644 index 00000000000..df3ede0860a --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/Procedures/ResolveScheduleName.g.cs @@ -0,0 +1,101 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteProcedures : RemoteBase + { + public void ResolveScheduleName(string accessor, string? namespaceName, string sourceName, string? functionName, bool rootNone, bool childNone, ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalResolveScheduleName(accessor, namespaceName, sourceName, functionName, rootNone, childNone, (ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalResolveScheduleName(string accessor, string? namespaceName, string sourceName, string? functionName, bool rootNone, bool childNone, ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.ResolveScheduleNameArgs(accessor, namespaceName, sourceName, functionName, rootNone, childNone), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ResolveScheduleName + { + [DataMember(Name = "Value")] + public string Value; + + public ResolveScheduleName(string Value) + { + this.Value = Value; + } + + public ResolveScheduleName() + { + this.Value = ""; + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ResolveScheduleNameArgs : Procedure, IProcedureArgs + { + [DataMember(Name = "accessor")] + public string Accessor; + [DataMember(Name = "namespace_name")] + public string? NamespaceName; + [DataMember(Name = "source_name")] + public string SourceName; + [DataMember(Name = "function_name")] + public string? FunctionName; + [DataMember(Name = "root_none")] + public bool RootNone; + [DataMember(Name = "child_none")] + public bool ChildNone; + + public ResolveScheduleNameArgs( + string Accessor, + string? NamespaceName, + string SourceName, + string? FunctionName, + bool RootNone, + bool ChildNone + ) + { + this.Accessor = Accessor; + this.NamespaceName = NamespaceName; + this.SourceName = SourceName; + this.FunctionName = FunctionName; + this.RootNone = RootNone; + this.ChildNone = ChildNone; + } + + public ResolveScheduleNameArgs() + { + this.Accessor = ""; + this.SourceName = ""; + } + + string IProcedureArgs.ProcedureName => "resolve_schedule_name"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs index 4b67c9da2ce..64447228388 100644 --- a/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/namespaces/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.11.0 (commit 33fe65db55dc769009e00053334c83522468e265). +// This was generated using spacetimedb cli version 2.11.0 (commit 2025539bb2b645718bb9f305106c40fc52d7b3af). #nullable enable From fd4afcdda43e312c1e808278f6b12357c09ef1ac Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Fri, 25 Sep 2026 14:19:21 -0500 Subject: [PATCH 48/49] Fix lint error --- crates/testing/tests/environment.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/testing/tests/environment.rs b/crates/testing/tests/environment.rs index b83e0b5f2cc..4236868bee8 100644 --- a/crates/testing/tests/environment.rs +++ b/crates/testing/tests/environment.rs @@ -130,8 +130,7 @@ async fn check_submodule_scope( .await; let error = result .result - .err() - .expect("submodule procedure read the root environment"); + .expect_err("submodule procedure read the root environment"); assert!( !format!("{error:#}").contains(cases.secret_marker), "procedure error exposed environment data" From 7ee3c500b147e09952ed3172ddeb1990871a090e Mon Sep 17 00:00:00 2001 From: Lisandro Crespo Date: Fri, 25 Sep 2026 15:33:10 -0500 Subject: [PATCH 49/49] Fix csharp-testsuite --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9017ac7bf41..b21619a9c38 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1410,7 +1410,7 @@ jobs: # Create temp global.json to target .NET 8 SDK for workload install echo '{"sdk":{"version":"8.0.100","rollForward":"latestFeature"}}' > global.json dotnet workload install wasi-experimental - rm global.json + git restore -- global.json - name: Override NuGet packages run: |