├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── copilot-instructions.md └── workflows │ ├── SignedPackageFileList.txt │ ├── SignedTemplateFileList.txt │ ├── build-docs.yml │ ├── build-library.yml │ ├── build-template.yml │ └── stale-issues.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Datasync.Toolkit.sln ├── Directory.Packages.props ├── LICENSE.md ├── README.md ├── azure.yaml ├── docs ├── css │ └── extra.css ├── in-depth │ ├── client │ │ ├── advanced │ │ │ └── maui-aot.md │ │ ├── auth.md │ │ ├── index.md │ │ └── online.md │ └── server │ │ ├── db │ │ ├── azuresql.md │ │ ├── cosmos-sdk.md │ │ ├── cosmos.md │ │ ├── in-memory.md │ │ ├── litedb.md │ │ ├── mongodb.md │ │ ├── mysql.md │ │ ├── pgsql.md │ │ └── sqlite.md │ │ ├── index.md │ │ └── openapi │ │ ├── net9.md │ │ ├── nswag.md │ │ └── swashbuckle.md ├── index.md ├── samples │ └── todoapp │ │ ├── avalonia.md │ │ ├── maui.md │ │ ├── server.md │ │ ├── unoplatform.md │ │ ├── winui3.md │ │ └── wpf.md └── tutorial │ ├── client │ ├── part-1.md │ ├── part-2.md │ └── part-3.md │ └── server │ ├── img │ ├── 2024-11-01-image1.png │ ├── 2024-11-01-image2.png │ ├── 2024-11-22-image1.png │ └── 2024-11-22-image2.png │ ├── part-1.md │ ├── part-2.md │ ├── part-3.md │ ├── part-4.md │ └── part-5.md ├── icon.png ├── infra ├── main.bicep ├── main.parameters.json ├── modules │ ├── appservice.bicep │ ├── azuresql.bicep │ ├── cosmos-mongodb.bicep │ └── cosmos.bicep ├── resources.bicep └── scripts │ ├── remove-runsettings.ps1 │ └── write-runsettings.ps1 ├── mkdocs.production.yml ├── mkdocs.shared.yml ├── mkdocs.yml ├── samples ├── Directory.Packages.props ├── datasync-server-cosmosdb-singlecontainer │ ├── Datasync.Server.CosmosDb.SingleContainer.sln │ ├── azure.yaml │ ├── infra │ │ ├── main.bicep │ │ ├── main.parameters.json │ │ └── resources.bicep │ └── src │ │ ├── Controllers │ │ ├── TodoItemController.cs │ │ └── TodoListController.cs │ │ ├── Models │ │ ├── TodoItem.cs │ │ └── TodoList.cs │ │ ├── Program.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── Sample.Datasync.Server.SingleContainer.csproj │ │ ├── Sample.Datasync.Server.SingleContainer.http │ │ ├── appsettings.Development.json │ │ └── appsettings.json ├── datasync-server │ ├── Sample.Datasync.Server.sln │ ├── azure.yaml │ ├── infra │ │ ├── main.bicep │ │ ├── main.parameters.json │ │ └── resources.bicep │ └── src │ │ └── Sample.Datasync.Server │ │ ├── Controllers │ │ ├── TodoItemController.cs │ │ └── TodoListController.cs │ │ ├── Db │ │ ├── AppDbContext.cs │ │ ├── TodoItem.cs │ │ └── TodoList.cs │ │ ├── Program.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── Sample.Datasync.Server.csproj │ │ ├── appsettings.Development.json │ │ └── appsettings.json ├── todoapp-mvc │ ├── TodoApp.Service │ │ ├── Controllers │ │ │ ├── HomeController.cs │ │ │ └── TodoItemsController.cs │ │ ├── Database │ │ │ ├── TodoContext.cs │ │ │ └── TodoItem.cs │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── TodoApp.Service.csproj │ │ ├── Views │ │ │ ├── Home │ │ │ │ └── Index.cshtml │ │ │ ├── Shared │ │ │ │ └── _Layout.cshtml │ │ │ ├── _ViewImports.cshtml │ │ │ └── _ViewStart.cshtml │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ ├── libman.json │ │ └── wwwroot │ │ │ ├── css │ │ │ └── site.css │ │ │ └── js │ │ │ └── site.js │ └── part5.sln ├── todoapp-tutorial │ ├── ClientApp │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── AssemblyInfo.cs │ │ ├── ClientApp.csproj │ │ ├── Converters │ │ │ └── BooleanToImageConverter.cs │ │ ├── Images │ │ │ ├── completed.png │ │ │ └── incomplete.png │ │ ├── Interfaces │ │ │ ├── IAlertService.cs │ │ │ ├── IAppInitializer.cs │ │ │ └── ITodoService.cs │ │ ├── MainWindow.xaml │ │ ├── MainWindow.xaml.cs │ │ ├── Models │ │ │ ├── OfflineClientEntity.cs │ │ │ └── TodoItem.cs │ │ ├── Services │ │ │ ├── AlertService.cs │ │ │ ├── AppInitializer.cs │ │ │ └── InMemoryTodoService.cs │ │ └── ViewModels │ │ │ └── TodoListViewModel.cs │ ├── ServerApp │ │ ├── Controllers │ │ │ └── TodoItemController.cs │ │ ├── Models │ │ │ └── TodoItem.cs │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── ServerApp.csproj │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ └── wwwroot │ │ │ ├── css │ │ │ └── site.css │ │ │ ├── favicon.ico │ │ │ ├── js │ │ │ └── site.js │ │ │ └── lib │ │ │ ├── bootstrap │ │ │ ├── LICENSE │ │ │ └── dist │ │ │ │ ├── css │ │ │ │ ├── bootstrap-grid.css │ │ │ │ ├── bootstrap-grid.css.map │ │ │ │ ├── bootstrap-grid.min.css │ │ │ │ ├── bootstrap-grid.min.css.map │ │ │ │ ├── bootstrap-grid.rtl.css │ │ │ │ ├── bootstrap-grid.rtl.css.map │ │ │ │ ├── bootstrap-grid.rtl.min.css │ │ │ │ ├── bootstrap-grid.rtl.min.css.map │ │ │ │ ├── bootstrap-reboot.css │ │ │ │ ├── bootstrap-reboot.css.map │ │ │ │ ├── bootstrap-reboot.min.css │ │ │ │ ├── bootstrap-reboot.min.css.map │ │ │ │ ├── bootstrap-reboot.rtl.css │ │ │ │ ├── bootstrap-reboot.rtl.css.map │ │ │ │ ├── bootstrap-reboot.rtl.min.css │ │ │ │ ├── bootstrap-reboot.rtl.min.css.map │ │ │ │ ├── bootstrap-utilities.css │ │ │ │ ├── bootstrap-utilities.css.map │ │ │ │ ├── bootstrap-utilities.min.css │ │ │ │ ├── bootstrap-utilities.min.css.map │ │ │ │ ├── bootstrap-utilities.rtl.css │ │ │ │ ├── bootstrap-utilities.rtl.css.map │ │ │ │ ├── bootstrap-utilities.rtl.min.css │ │ │ │ ├── bootstrap-utilities.rtl.min.css.map │ │ │ │ ├── bootstrap.css │ │ │ │ ├── bootstrap.css.map │ │ │ │ ├── bootstrap.min.css │ │ │ │ ├── bootstrap.min.css.map │ │ │ │ ├── bootstrap.rtl.css │ │ │ │ ├── bootstrap.rtl.css.map │ │ │ │ ├── bootstrap.rtl.min.css │ │ │ │ └── bootstrap.rtl.min.css.map │ │ │ │ └── js │ │ │ │ ├── bootstrap.bundle.js │ │ │ │ ├── bootstrap.bundle.js.map │ │ │ │ ├── bootstrap.bundle.min.js │ │ │ │ ├── bootstrap.bundle.min.js.map │ │ │ │ ├── bootstrap.esm.js │ │ │ │ ├── bootstrap.esm.js.map │ │ │ │ ├── bootstrap.esm.min.js │ │ │ │ ├── bootstrap.esm.min.js.map │ │ │ │ ├── bootstrap.js │ │ │ │ ├── bootstrap.js.map │ │ │ │ ├── bootstrap.min.js │ │ │ │ └── bootstrap.min.js.map │ │ │ ├── jquery-validation-unobtrusive │ │ │ ├── LICENSE.txt │ │ │ └── dist │ │ │ │ ├── jquery.validate.unobtrusive.js │ │ │ │ └── jquery.validate.unobtrusive.min.js │ │ │ ├── jquery-validation │ │ │ ├── LICENSE.md │ │ │ └── dist │ │ │ │ ├── additional-methods.js │ │ │ │ ├── additional-methods.min.js │ │ │ │ ├── jquery.validate.js │ │ │ │ └── jquery.validate.min.js │ │ │ └── jquery │ │ │ ├── LICENSE.txt │ │ │ └── dist │ │ │ ├── jquery.js │ │ │ ├── jquery.min.js │ │ │ ├── jquery.min.map │ │ │ ├── jquery.slim.js │ │ │ ├── jquery.slim.min.js │ │ │ └── jquery.slim.min.map │ └── todoapp.sln └── todoapp │ ├── Samples.TodoApp.sln │ ├── TodoApp.Avalonia │ ├── Directory.Build.props │ ├── TodoApp.Avalonia.Android │ │ ├── Icon.png │ │ ├── MainActivity.cs │ │ ├── Properties │ │ │ └── AndroidManifest.xml │ │ ├── Resources │ │ │ ├── AboutResources.txt │ │ │ ├── drawable-night-v31 │ │ │ │ └── avalonia_anim.xml │ │ │ ├── drawable-v31 │ │ │ │ └── avalonia_anim.xml │ │ │ ├── drawable │ │ │ │ └── splash_screen.xml │ │ │ ├── values-night │ │ │ │ └── colors.xml │ │ │ ├── values-v31 │ │ │ │ └── styles.xml │ │ │ └── values │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ └── TodoApp.Avalonia.Android.csproj │ ├── TodoApp.Avalonia.Desktop │ │ ├── Program.cs │ │ ├── TodoApp.Avalonia.Desktop.csproj │ │ └── app.manifest │ ├── TodoApp.Avalonia.iOS │ │ ├── AppDelegate.cs │ │ ├── Entitlements.plist │ │ ├── Info.plist │ │ ├── Main.cs │ │ ├── Resources │ │ │ └── LaunchScreen.xib │ │ └── TodoApp.Avalonia.iOS.csproj │ ├── TodoApp.Avalonia.sln │ └── TodoApp.Avalonia │ │ ├── App.axaml │ │ ├── App.axaml.cs │ │ ├── Assets │ │ └── avalonia-logo.ico │ │ ├── Database │ │ ├── AppDbContext.cs │ │ ├── DbContextInitializer.cs │ │ ├── IDbInitializer.cs │ │ ├── OfflineClientEntry.cs │ │ └── ToDoItem.cs │ │ ├── Services │ │ ├── DialogManager.cs │ │ ├── IDialogBus.cs │ │ ├── INotificationService.cs │ │ └── LoggingHandler.cs │ │ ├── TodoApp.Avalonia.csproj │ │ ├── ViewModels │ │ ├── DesignTimeViewModels.cs │ │ ├── TodoItemViewModel.cs │ │ ├── TodoListViewModel.cs │ │ └── ViewModelBase.cs │ │ └── Views │ │ ├── MainView.axaml │ │ ├── MainView.axaml.cs │ │ ├── MainWindow.axaml │ │ └── MainWindow.axaml.cs │ ├── TodoApp.MAUI │ ├── App.xaml │ ├── App.xaml.cs │ ├── AppShell.xaml │ ├── AppShell.xaml.cs │ ├── MainPage.xaml │ ├── MainPage.xaml.cs │ ├── MauiProgram.cs │ ├── Models │ │ ├── AppDbContext.cs │ │ ├── IDbInitializer.cs │ │ ├── OfflineClientEntity.cs │ │ └── TodoItem.cs │ ├── Platforms │ │ ├── Android │ │ │ ├── AndroidManifest.xml │ │ │ ├── MainActivity.cs │ │ │ ├── MainApplication.cs │ │ │ └── Resources │ │ │ │ └── values │ │ │ │ └── colors.xml │ │ ├── Windows │ │ │ ├── App.xaml │ │ │ ├── App.xaml.cs │ │ │ ├── Package.appxmanifest │ │ │ └── app.manifest │ │ └── iOS │ │ │ ├── AppDelegate.cs │ │ │ ├── Info.plist │ │ │ ├── Program.cs │ │ │ └── Resources │ │ │ └── PrivacyInfo.xcprivacy │ ├── Properties │ │ └── launchSettings.json │ ├── Resources │ │ ├── AppIcon │ │ │ ├── appicon.svg │ │ │ └── appiconfg.svg │ │ ├── Fonts │ │ │ ├── FluentUI.cs │ │ │ ├── OpenSans-Regular.ttf │ │ │ └── OpenSans-Semibold.ttf │ │ ├── Images │ │ │ ├── additem.png │ │ │ ├── completed.png │ │ │ ├── dotnet_bot.png │ │ │ └── refresh.png │ │ ├── Raw │ │ │ └── AboutAssets.txt │ │ ├── Splash │ │ │ └── splash.svg │ │ └── Styles │ │ │ ├── Colors.xaml │ │ │ └── Styles.xaml │ ├── Services │ │ ├── AlertService.cs │ │ ├── LoggingHandler.cs │ │ └── SqliteHelper.cs │ ├── TodoApp.MAUI.csproj │ └── ViewModels │ │ └── MainViewModel.cs │ ├── TodoApp.Uno │ ├── .editorconfig │ ├── .run │ │ ├── Readme.md │ │ └── TodoApp.Uno.run.xml │ ├── .vscode │ │ ├── extensions.json │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ ├── .vsconfig │ ├── Directory.Build.props │ ├── Directory.Build.targets │ ├── Directory.Packages.props │ ├── TodoApp.Uno.sln │ ├── TodoApp.Uno │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── Assets │ │ │ ├── AddItem.png │ │ │ ├── Icons │ │ │ │ ├── icon.svg │ │ │ │ └── icon_foreground.svg │ │ │ ├── Images │ │ │ │ └── back.svg │ │ │ ├── LockScreenLogo.scale-200.png │ │ │ ├── RefreshItems.png │ │ │ ├── SharedAssets.md │ │ │ ├── Splash │ │ │ │ └── splash_screen.svg │ │ │ ├── SplashScreen.scale-200.png │ │ │ ├── Square150x150Logo.scale-200.png │ │ │ ├── Square44x44Logo.scale-200.png │ │ │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ │ │ ├── StoreLogo.png │ │ │ └── Wide310x150Logo.scale-200.png │ │ ├── Database │ │ │ ├── AppDbContext.cs │ │ │ ├── IDbInitializer.cs │ │ │ ├── OfflineClientEntity.cs │ │ │ └── TodoItem.cs │ │ ├── GlobalUsings.cs │ │ ├── Package.appxmanifest │ │ ├── Platforms │ │ │ ├── Android │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── Assets │ │ │ │ │ └── AboutAssets.txt │ │ │ │ ├── Main.Android.cs │ │ │ │ ├── MainActivity.Android.cs │ │ │ │ ├── Resources │ │ │ │ │ ├── AboutResources.txt │ │ │ │ │ └── values │ │ │ │ │ │ ├── Strings.xml │ │ │ │ │ │ └── Styles.xml │ │ │ │ └── environment.conf │ │ │ ├── Desktop │ │ │ │ └── Program.cs │ │ │ ├── MacCatalyst │ │ │ │ ├── Entitlements.plist │ │ │ │ ├── Info.plist │ │ │ │ ├── Main.maccatalyst.cs │ │ │ │ └── Media.xcassets │ │ │ │ │ └── LaunchImages.launchimage │ │ │ │ │ └── Contents.json │ │ │ ├── WebAssembly │ │ │ │ ├── LinkerConfig.xml │ │ │ │ ├── Program.cs │ │ │ │ ├── WasmCSS │ │ │ │ │ └── Fonts.css │ │ │ │ ├── WasmScripts │ │ │ │ │ └── AppManifest.js │ │ │ │ ├── manifest.webmanifest │ │ │ │ └── wwwroot │ │ │ │ │ ├── staticwebapp.config.json │ │ │ │ │ └── web.config │ │ │ └── iOS │ │ │ │ ├── Entitlements.plist │ │ │ │ ├── Info.plist │ │ │ │ ├── Main.iOS.cs │ │ │ │ ├── Media.xcassets │ │ │ │ └── LaunchImages.launchimage │ │ │ │ │ └── Contents.json │ │ │ │ └── PrivacyInfo.xcprivacy │ │ ├── Presentation │ │ │ ├── Shell.xaml │ │ │ ├── Shell.xaml.cs │ │ │ └── ShellViewModel.cs │ │ ├── Properties │ │ │ ├── PublishProfiles │ │ │ │ ├── win-arm64.pubxml │ │ │ │ ├── win-x64.pubxml │ │ │ │ └── win-x86.pubxml │ │ │ └── launchSettings.json │ │ ├── ReadMe.md │ │ ├── Services │ │ │ └── LoggingHandler.cs │ │ ├── Strings │ │ │ ├── en │ │ │ │ └── Resources.resw │ │ │ ├── es │ │ │ │ └── Resources.resw │ │ │ ├── fr │ │ │ │ └── Resources.resw │ │ │ └── pt-BR │ │ │ │ └── Resources.resw │ │ ├── TodoApp.Uno.csproj │ │ ├── ViewModels │ │ │ ├── NotificationEventArgs.cs │ │ │ ├── TodoItemViewModel.cs │ │ │ └── TodoListViewModel.cs │ │ ├── Views │ │ │ ├── TodoListPage.xaml │ │ │ └── TodoListPage.xaml.cs │ │ ├── app.manifest │ │ ├── appsettings.development.json │ │ └── appsettings.json │ └── global.json │ ├── TodoApp.WPF │ ├── App.xaml │ ├── App.xaml.cs │ ├── AssemblyInfo.cs │ ├── Converters │ │ └── BooleanToImageConverter.cs │ ├── Database │ │ ├── AppDbContext.cs │ │ ├── IDbInitializer.cs │ │ ├── OfflineClientEntity.cs │ │ └── TodoItem.cs │ ├── Images │ │ ├── completed.png │ │ └── incomplete.png │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── Services │ │ ├── AlertService.cs │ │ └── LoggingHandler.cs │ ├── TodoApp.WPF.csproj │ └── ViewModels │ │ └── TodoListViewModel.cs │ └── TodoApp.WinUI3 │ ├── App.xaml │ ├── App.xaml.cs │ ├── Assets │ ├── AddItem.png │ ├── LockScreenLogo.scale-200.png │ ├── RefreshItems.png │ ├── SplashScreen.scale-200.png │ ├── Square150x150Logo.scale-200.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── StoreLogo.png │ └── Wide310x150Logo.scale-200.png │ ├── Database │ ├── AppDbContext.cs │ ├── IDbInitializer.cs │ ├── OfflineClientEntity.cs │ └── TodoItem.cs │ ├── Package.appxmanifest │ ├── Properties │ └── launchSettings.json │ ├── Services │ └── LoggingHandler.cs │ ├── TodoApp.WinUI3.csproj │ ├── ViewModels │ ├── NotificationEventArgs.cs │ ├── TodoItemViewModel.cs │ └── TodoListViewModel.cs │ ├── Views │ ├── TodoListPage.xaml │ └── TodoListPage.xaml.cs │ └── app.manifest ├── src ├── CommunityToolkit.Datasync.Client │ ├── Authentication │ │ ├── AuthenticationProvider.cs │ │ ├── AuthenticationToken.cs │ │ └── GenericAuthenticationProvider.cs │ ├── CommunityToolkit.Datasync.Client.csproj │ ├── Exceptions │ │ ├── ArgumentValidationException.cs │ │ ├── ConflictException.cs │ │ ├── DatasyncException.cs │ │ ├── DatasyncHttpException.cs │ │ ├── DatasyncPullException.cs │ │ ├── DatasyncQueueException.cs │ │ └── EntityDoesNotExistException.cs │ ├── Http │ │ ├── BasicHttpClientFactory.cs │ │ ├── DatasyncHttpHeaders.cs │ │ ├── HttpClientExtensions.cs │ │ ├── HttpClientFactory.cs │ │ ├── HttpClientOptions.cs │ │ └── Platform.cs │ ├── Offline │ │ ├── ConflictResolvers.cs │ │ ├── DatasyncOfflineOptionsBuilder.cs │ │ ├── DeltaTokenStore │ │ │ ├── DatasyncDeltaToken.cs │ │ │ ├── DefaultDeltaTokenStore.cs │ │ │ └── IDeltaTokenStore.cs │ │ ├── DoNotSynchronizeAttribute.cs │ │ ├── Extensions.cs │ │ ├── IConflictResolver.cs │ │ ├── Models │ │ │ ├── ConflictResolution.cs │ │ │ ├── EntityDatasyncOptions.cs │ │ │ ├── OfflineOptions.cs │ │ │ ├── PullOptions.cs │ │ │ ├── PullRequest.cs │ │ │ └── PullResult.cs │ │ ├── OfflineDbContext.cs │ │ ├── Operations │ │ │ ├── AddOperation.cs │ │ │ ├── DeleteOperation.cs │ │ │ ├── ExecutableOperation.cs │ │ │ ├── IPullOperationManager.cs │ │ │ ├── PullOperationManager.cs │ │ │ └── ReplaceOperation.cs │ │ ├── OperationsQueue │ │ │ ├── DatasyncOperation.cs │ │ │ ├── Extensions.cs │ │ │ ├── IOperationsQueueManager.cs │ │ │ ├── OperationsQueueManager.cs │ │ │ ├── PushOptions.cs │ │ │ └── PushResult.cs │ │ └── PullRequestBuilder.cs │ ├── Paging │ │ ├── AsyncPageable.cs │ │ ├── ConcurrentObservableCollection.cs │ │ ├── FuncAsyncPageable.cs │ │ ├── IAsyncPageable.cs │ │ └── Page.cs │ ├── Query │ │ ├── DatasyncPullQuery.cs │ │ ├── DatasyncQueryable.cs │ │ ├── IAsyncEnumerableExtensions.cs │ │ ├── IDatasyncPullQuery.cs │ │ ├── IDatasyncQueryMethods.cs │ │ ├── IDatasyncQueryable.cs │ │ ├── IDatasyncQueryableExtensions.cs │ │ ├── Linq │ │ │ ├── ExpressionExtensions.cs │ │ │ ├── FilterBuildingExpressionVisitor.cs │ │ │ ├── LookupTables.cs │ │ │ ├── MemberInfoKey.cs │ │ │ ├── OperatorKinds.cs │ │ │ ├── OrderByNode.cs │ │ │ ├── QueryDescription.cs │ │ │ ├── QueryNodeVisitor.cs │ │ │ ├── QueryNodes.cs │ │ │ ├── QueryTranslator.cs │ │ │ └── VisitorHelper.cs │ │ └── OData │ │ │ ├── ODataExpressionVisitor.cs │ │ │ ├── ODataQueryParameters.cs │ │ │ ├── QueryDescriptionExtensions.cs │ │ │ └── TableLookupExtensions.cs │ ├── Serialization │ │ ├── DatasyncSerializer.cs │ │ ├── DateTimeConverter.cs │ │ ├── DateTimeOffsetConverter.cs │ │ ├── EntityMetadata.cs │ │ ├── EntityResolver.cs │ │ ├── JsonExtensions.cs │ │ ├── SpatialGeoJsonConverter.cs │ │ └── TimeOnlyConverter.cs │ ├── Service │ │ ├── DatasyncServiceClient.cs │ │ ├── DatasyncServiceOptions.cs │ │ ├── IDatasyncServiceClient.cs │ │ ├── IDatasyncServiceClientExtensions.cs │ │ ├── ServiceErrorMessages.cs │ │ └── ServiceResponse.cs │ ├── Threading │ │ ├── AsyncLockDictionary.cs │ │ ├── DisposableLock.cs │ │ ├── DisposeAction.cs │ │ ├── LockManager.cs │ │ └── QueueHandler.cs │ └── ThrowIf.cs ├── CommunityToolkit.Datasync.Server.Abstractions │ ├── CommunityToolkit.Datasync.Server.Abstractions.csproj │ ├── Exceptions │ │ ├── DatasyncToolkitException.cs │ │ ├── HttpException.cs │ │ └── RepositoryException.cs │ ├── Http │ │ └── HttpStatusCodes.cs │ ├── Json │ │ ├── DateTimeConverter.cs │ │ ├── DateTimeOffsetConverter.cs │ │ ├── JsonExtensions.cs │ │ ├── SpatialGeoJsonConverter.cs │ │ └── TimeOnlyConverter.cs │ └── Tables │ │ ├── AccessControlProvider.cs │ │ ├── IAccessControlProvider.cs │ │ ├── IRepository.cs │ │ ├── ITableData.cs │ │ └── TableOperation.cs ├── CommunityToolkit.Datasync.Server.Automapper │ ├── CommunityToolkit.Datasync.Server.Automapper.csproj │ └── MappedTableRepository.cs ├── CommunityToolkit.Datasync.Server.CosmosDb │ ├── CommunityToolkit.Datasync.Server.CosmosDb.csproj │ ├── CosmosSharedTableOptions.cs │ ├── CosmosSingleTableOptions.cs │ ├── CosmosTableData.cs │ ├── CosmosTableDataOfT.cs │ ├── CosmosTableOptions.cs │ ├── CosmosTableRepository.cs │ ├── Extensions │ │ └── IQueryableExtensions.cs │ └── ICosmosTableOptions.cs ├── CommunityToolkit.Datasync.Server.EntityFrameworkCore │ ├── BaseEntityTableData.cs │ ├── CommunityToolkit.Datasync.Server.EntityFrameworkCore.csproj │ ├── CosmosEntityTableData.cs │ ├── EntityTableData.cs │ ├── EntityTableRepository.cs │ ├── RepositoryControlledEntityTableData.cs │ ├── SqliteEntityTableData.cs │ └── UpdatedByRepositoryAttribute.cs ├── CommunityToolkit.Datasync.Server.InMemory │ ├── CommunityToolkit.Datasync.Server.InMemory.csproj │ ├── DatasyncExtensions.cs │ ├── InMemoryRepository.cs │ └── InMemoryTableData.cs ├── CommunityToolkit.Datasync.Server.LiteDb │ ├── CommunityToolkit.Datasync.Server.LiteDb.csproj │ ├── LiteDbRepository.cs │ └── LiteDbTableData.cs ├── CommunityToolkit.Datasync.Server.MongoDB │ ├── CommunityToolkit.Datasync.Server.MongoDB.csproj │ ├── MongoDBRepository.cs │ └── MongoTableData.cs ├── CommunityToolkit.Datasync.Server.NSwag │ ├── CommunityToolkit.Datasync.Server.NSwag.csproj │ ├── DatasyncOperationProcessor.cs │ ├── DatasyncSchemaProcessor.cs │ └── OpenApiExtensions.cs ├── CommunityToolkit.Datasync.Server.OpenApi │ ├── CommunityToolkit.Datasync.Server.OpenApi.csproj │ ├── DatasyncOperationTransformer.cs │ ├── InternalExtensions.cs │ └── OpenApiExtensions.cs ├── CommunityToolkit.Datasync.Server.Swashbuckle │ ├── CommunityToolkit.Datasync.Server.Swashbuckle.csproj │ ├── DatasyncDocumentFilter.cs │ ├── DatasyncOperationExtensions.cs │ └── SwaggerGenExtensions.cs ├── CommunityToolkit.Datasync.Server │ ├── CommunityToolkit.Datasync.Server.csproj │ ├── Controllers │ │ ├── TableController.Create.cs │ │ ├── TableController.Delete.cs │ │ ├── TableController.Query.cs │ │ ├── TableController.Read.cs │ │ ├── TableController.Replace.cs │ │ └── TableController.cs │ ├── Extensions │ │ ├── InternalExtensions.cs │ │ └── PublicExtensions.cs │ ├── Filters │ │ └── DatasyncControllerAttribute.cs │ ├── Models │ │ ├── DatasyncServiceOptions.cs │ │ ├── IDatasyncServiceOptions.cs │ │ ├── ModelCache.cs │ │ ├── PagedResult.cs │ │ ├── Repository.cs │ │ ├── RepositoryUpdatedEventArgs.cs │ │ └── TableControllerOptions.cs │ └── OData │ │ ├── DatasyncFilterBinder.cs │ │ └── GeospatialFunctions.cs └── Directory.Build.props ├── templates ├── DatasyncTemplates.csproj └── Template.DatasyncServer │ ├── .template.config │ └── template.json │ ├── Controllers │ └── TodoItemController.cs │ ├── Models │ ├── AppDbContext.cs │ └── TodoItem.cs │ ├── Program.cs │ ├── Properties │ └── serviceDependencies.json │ ├── Template.DatasyncServer.csproj.template │ ├── appsettings.Development.json │ └── appsettings.json ├── tests ├── .editorconfig ├── CommunityToolkit.Datasync.Client.Test │ ├── Authentication │ │ └── GenericAuthenticationProvider_Tests.cs │ ├── CommunityToolkit.Datasync.Client.Test.csproj │ ├── Exceptions │ │ └── ArgumentValidationException_Tests.cs │ ├── GlobalUsings.cs │ ├── Helpers │ │ ├── ByteVersionMovie.cs │ │ ├── ClientMovieWithLocalData.cs │ │ ├── ClientTestData.cs │ │ ├── Disposable.cs │ │ ├── EndpointTestCases.cs │ │ ├── IntegrationDbContext.cs │ │ ├── ServiceApplicationFactory.cs │ │ └── ServiceTest.cs │ ├── Http │ │ ├── HttpClientExtensions_Tests.cs │ │ ├── HttpClientFactory_Tests.cs │ │ ├── HttpClientOptions_Tests.cs │ │ └── Platform_Tests.cs │ ├── Live │ │ └── SampleServerTests.cs │ ├── Offline │ │ ├── ConflictResolver_Tests.cs │ │ ├── DatasyncOfflineOptionsBuilder_Tests.cs │ │ ├── DefaultDeltaTokenStore_Tests.cs │ │ ├── DynamicProxies_Tests.cs │ │ ├── Helpers │ │ │ ├── BaseTest.cs │ │ │ └── TestDbContext.cs │ │ ├── Integration_Pull_Tests.cs │ │ ├── Integration_Push_Tests.cs │ │ ├── OfflineDbContext_Tests.cs │ │ ├── Operations │ │ │ ├── AddOperation_Tests.cs │ │ │ ├── DeleteOperation_Tests.cs │ │ │ ├── ExecutableOperation_Tests.cs │ │ │ ├── PullOperationManager_Tests.cs │ │ │ └── ReplaceOperation_Tests.cs │ │ └── OperationsQueueManager_Tests.cs │ ├── Paging │ │ └── ConcurrentObservableCollection_Tests.cs │ ├── Query │ │ ├── IDatasyncPullQuery_Tests.cs │ │ ├── IDatasyncQueryable_Tests.cs │ │ ├── Linq │ │ │ ├── ExpressionExtension_Tests.cs │ │ │ ├── FilterBuildingExpressionVisitor_Tests.cs │ │ │ ├── ImplicitConversion_Tests.cs │ │ │ ├── MemberInfoKey_Tests.cs │ │ │ ├── QueryNode_Tests.cs │ │ │ └── QueryTranslator_Tests.cs │ │ └── OData │ │ │ ├── ODataExpressionVisitor_Tests.cs │ │ │ └── TableLookup_Tests.cs │ ├── Serialization │ │ ├── DatasyncSerializer_Tests.cs │ │ ├── DateTimeConverter_Tests.cs │ │ ├── DateTimeOffsetConverter_Tests.cs │ │ ├── EntityResolver_Tests.cs │ │ ├── SerializerTests.cs │ │ └── TimeOnlyConverter_Tests.cs │ ├── Service │ │ ├── DatasyncServiceClient_Tests.cs │ │ ├── Integration_Query_Tests.cs │ │ ├── Integration_Tests.cs │ │ └── ServiceResponse_Tests.cs │ ├── Threading │ │ ├── AsyncLockDictionary_Tests.cs │ │ ├── DisposableLock_Tests.cs │ │ ├── DisposeAction_Tests.cs │ │ └── QueueHandler_Tests.cs │ └── ThrowIf_Tests.cs ├── CommunityToolkit.Datasync.Server.Abstractions.Test │ ├── CommunityToolkit.Datasync.Server.Abstractions.Test.csproj │ ├── GlobalUsings.cs │ └── Json │ │ ├── DateTimeConverter_Tests.cs │ │ ├── DateTimeOffsetConverter_Tests.cs │ │ ├── SerializerTests.cs │ │ └── TimeOnlyConverter_Tests.cs ├── CommunityToolkit.Datasync.Server.Automapper.Test │ ├── CommunityToolkit.Datasync.Server.Automapper.Test.csproj │ ├── GlobalUsings.cs │ ├── Helpers │ │ ├── MapperProfile.cs │ │ └── MovieDto.cs │ └── MappedTableRepository_Tests.cs ├── CommunityToolkit.Datasync.Server.CosmosDb.Test │ ├── CommunityToolkit.Datasync.Server.CosmosDb.Test.csproj │ ├── CosmosDbRepository_Tests.cs │ ├── CosmosTableData_Tests.cs │ ├── Models │ │ └── CosmosDbMovie.cs │ ├── Options │ │ └── PackedKeyOptions.cs │ └── PackedKeyRepository_Tests.cs ├── CommunityToolkit.Datasync.Server.EntityFrameworkCore.Test │ ├── AzureSqlEntityTableRepository_Tests.cs │ ├── CommunityToolkit.Datasync.Server.EntityFrameworkCore.Test.csproj │ ├── CosmosEntityTableRepository_Tests.cs │ ├── EntityTableData_Tests.cs │ ├── GlobalUsings.cs │ ├── LiveTestsCollection.cs │ ├── MySqlEntityTableRepository_Tests.cs │ ├── PgEntityTableRepository_Tests.cs │ ├── RepositoryControlledEntityTableRepository_Tests.cs │ └── SqliteEntityTableRepository_Tests.cs ├── CommunityToolkit.Datasync.Server.InMemory.Test │ ├── CommunityToolkit.Datasync.Server.InMemory.Test.csproj │ ├── GlobalUsings.cs │ ├── InMemoryRepository_Tests.cs │ └── InMemoryTableData_Tests.cs ├── CommunityToolkit.Datasync.Server.LiteDb.Test │ ├── CommunityToolkit.Datasync.Server.LiteDb.Test.csproj │ ├── GlobalUsings.cs │ ├── LiteDbRepository_Tests.cs │ └── LiteDbTableData_Tests.cs ├── CommunityToolkit.Datasync.Server.MongoDB.Test │ ├── CommunityToolkit.Datasync.Server.MongoDB.Test.csproj │ ├── CosmosMongoRepository_Tests.cs │ ├── MongoDBRepository_Tests.cs │ └── MongoTableData_Tests.cs ├── CommunityToolkit.Datasync.Server.NSwag.Test │ ├── CommunityToolkit.Datasync.Server.NSwag.Test.csproj │ ├── GlobalUsings.cs │ ├── NSwag_Tests.cs │ ├── Service │ │ ├── Controllers.cs │ │ ├── Models.cs │ │ ├── NSwagServer.cs │ │ └── ServiceDbContext.cs │ └── swagger.json ├── CommunityToolkit.Datasync.Server.OpenApi.Test │ ├── CommunityToolkit.Datasync.Server.OpenApi.Test.csproj │ ├── GlobalUsings.cs │ ├── OpenApi_Tests.cs │ ├── Service │ │ ├── Controllers.cs │ │ ├── Models.cs │ │ ├── OpenApiServer.cs │ │ └── ServiceDbContext.cs │ └── openapi.json ├── CommunityToolkit.Datasync.Server.Swashbuckle.Test │ ├── CommunityToolkit.Datasync.Server.Swashbuckle.Test.csproj │ ├── Service │ │ ├── Controllers.cs │ │ ├── Models.cs │ │ ├── ServiceDbContext.cs │ │ └── SwashbuckleServer.cs │ ├── Swashbuckle_Tests.cs │ └── swagger.json ├── CommunityToolkit.Datasync.Server.Test │ ├── CommunityToolkit.Datasync.Server.Test.csproj │ ├── Controllers │ │ ├── TableController_Base_Tests.cs │ │ ├── TableController_Create_Tests.cs │ │ ├── TableController_Delete_Tests.cs │ │ ├── TableController_Query_Tests.cs │ │ ├── TableController_Read_Tests.cs │ │ └── TableController_Replace_Tests.cs │ ├── Extensions │ │ └── InternalExtensions_Tests.cs │ ├── Filters │ │ └── DatasyncControllerAttribute_Tests.cs │ ├── GlobalUsings.cs │ ├── Helpers │ │ ├── BaseTest.cs │ │ ├── ExposedTableController.cs │ │ ├── Extensions.cs │ │ ├── LiveControllerTests.cs │ │ ├── LiveTestsCollection.cs │ │ ├── ObjectValidator.cs │ │ ├── ServiceApplicationFactory.cs │ │ └── ServiceTest.cs │ ├── Live │ │ ├── AzureSQL_Controller_Tests.cs │ │ ├── CosmosMongo_Controller_Tests.cs │ │ ├── Cosmos_Controller_Tests.cs │ │ ├── InMemory_Controller_Tests.cs │ │ ├── LiteDb_Controller_Tests.cs │ │ ├── MongoDB_Controller_Tests.cs │ │ ├── MySQL_Controller_Tests.cs │ │ └── PgSQL_Controller_Tests.cs │ ├── Models │ │ ├── DatasyncServiceOptions_Tests.cs │ │ ├── PagedResult_Tests.cs │ │ └── TableControllerOptions_Tests.cs │ ├── OData │ │ └── GeospatialFunctions_Tests.cs │ └── Service │ │ ├── Create_Tests.cs │ │ ├── Delete_Tests.cs │ │ ├── Query_Tests.cs │ │ ├── Read_Tests.cs │ │ └── Replace_Tests.cs ├── CommunityToolkit.Datasync.TestCommon │ ├── CommunityToolkit.Datasync.TestCommon.csproj │ ├── Databases │ │ ├── AzureSql │ │ │ ├── AzureSqlDbContext.cs │ │ │ └── AzureSqlEntityMovie.cs │ │ ├── Base │ │ │ └── BaseDbContext.cs │ │ ├── Client │ │ │ ├── ClientKitchenSink.cs │ │ │ ├── ClientMovie.cs │ │ │ └── ClientObject.cs │ │ ├── ConnectionStrings.cs │ │ ├── CosmosDb │ │ │ ├── CosmosDbContext.cs │ │ │ └── CosmosEntityMovie.cs │ │ ├── InMemory │ │ │ ├── InMemoryKitchenSink.cs │ │ │ └── InMemoryMovie.cs │ │ ├── LiteDb │ │ │ └── LiteDbMovie.cs │ │ ├── LoggingExtensions.cs │ │ ├── MongoDB │ │ │ ├── MongoDBContext.cs │ │ │ └── MongoDBMovie.cs │ │ ├── MySQL │ │ │ ├── MysqlDbContext.cs │ │ │ └── MysqlEntityMovie.cs │ │ ├── Postgresql │ │ │ ├── PgDbContext.cs │ │ │ └── PgEntityMovie.cs │ │ ├── RepositoryControlled │ │ │ ├── RepositoryControlledDbContext.cs │ │ │ └── RepositoryControlledEntityMovie.cs │ │ └── Sqlite │ │ │ ├── SqliteDbContext.cs │ │ │ ├── SqliteEntityMovie.cs │ │ │ └── SqliteExtensions.cs │ ├── Fixtures │ │ ├── MongoDatabaseFixture.cs │ │ ├── MsSqlDatabaseFixture.cs │ │ ├── MySqlDatabaseFixture.cs │ │ ├── MySqlTestFixture.cs │ │ └── PostgreSqlDatabaseFixture.cs │ ├── FluentExtensions │ │ ├── HttpExceptionAssertions.cs │ │ ├── ObjectAssertions.cs │ │ └── StringAssertions.cs │ ├── LibraryExtensions.cs │ ├── Mocks │ │ └── MockDelegatingHandler.cs │ ├── Models │ │ ├── ClientTableData.cs │ │ ├── Country.cs │ │ ├── IKitchenSink.cs │ │ ├── IMovie.cs │ │ ├── MovieBase.cs │ │ ├── PageOfItems.cs │ │ └── TableData.cs │ ├── RepositoryTests.cs │ └── TestData │ │ ├── CountryData.cs │ │ ├── ITableData_TestData.cs │ │ ├── Movies.cs │ │ └── countries.json ├── CommunityToolkit.Datasync.TestService │ ├── AccessControlProviders │ │ └── MovieAccessControlProvider.cs │ ├── CommunityToolkit.Datasync.TestService.csproj │ ├── Controllers │ │ ├── AuthorizedMovieController.cs │ │ ├── InMemoryKitchenSinkController.cs │ │ ├── InMemoryMovieController.cs │ │ ├── InMemoryPagedMovieController.cs │ │ └── InMemorySoftDeletedMovieController.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── appsettings.Development.json │ └── appsettings.json └── Directory.Build.props └── tools └── GetBuildVersion.psm1 /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: Requires Triage 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/copilot-instructions.md: -------------------------------------------------------------------------------- 1 | # Datasync Community Toolkit 2 | 3 | This is a set of instructions for the GitHub Copilot to support the Datasync Community Toolkit. 4 | 5 | ## Project Layout 6 | 7 | * `/docs` - documentation, mostly Markdown supporting `mkdocs` document generation. 8 | * `/infra` - infrastructure definition to support live testing. 9 | * `/samples` - sample code for the library. 10 | * `/src` - source code for the NuGet packages. 11 | * `/templates` - the template source code. 12 | * `/tests` - the test projects 13 | -------------------------------------------------------------------------------- /.github/workflows/SignedPackageFileList.txt: -------------------------------------------------------------------------------- 1 | **/CommunityToolkit.Datasync.Client 2 | **/CommunityToolkit.Datasync.Server.Abstractions 3 | **/CommunityToolkit.Datasync.Server.Automapper 4 | **/CommunityToolkit.Datasync.Server.CosmosDb 5 | **/CommunityToolkit.Datasync.Server.EntityFrameworkCore 6 | **/CommunityToolkit.Datasync.Server.InMemory 7 | **/CommunityToolkit.Datasync.Server.LiteDb 8 | **/CommunityToolkit.Datasync.Server.MongoDB 9 | **/CommunityToolkit.Datasync.Server.NSwag 10 | **/CommunityToolkit.Datasync.Server.OpenApi 11 | **/CommunityToolkit.Datasync.Server.Swashbuckle 12 | **/CommunityToolkit.Datasync.Server 13 | -------------------------------------------------------------------------------- /.github/workflows/SignedTemplateFileList.txt: -------------------------------------------------------------------------------- 1 | **/CommunityToolkit.Datasync.Server.Template.CSharp -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # .NET Community Toolkit 2 | 3 | Copyright © .NET Foundation and Contributors 4 | 5 | All rights reserved. 6 | 7 | ## MIT License (MIT) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 10 | documentation files (the “Software”), to deal in the Software without restriction, including without limitation 11 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 12 | and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 19 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /azure.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json 2 | 3 | ## 4 | ## This AZD template will create all the resources necessary to 5 | ## test the Community Toolkit/Datasync libraries, plus deploy an 6 | ## app service (on free tier) that talks to the AzSQL service 7 | ## for the TODO Sample Service 8 | ## 9 | 10 | name: communitytoolkit-datasync-test-services 11 | 12 | hooks: 13 | postprovision: 14 | posix: 15 | interactive: true 16 | shell: sh 17 | run: ./infra/scripts/write-runsettings.sh 18 | windows: 19 | interactive: true 20 | shell: pwsh 21 | run: ./infra/scripts/write-runsettings.ps1 22 | 23 | predown: 24 | posix: 25 | interactive: true 26 | shell: sh 27 | run: ./infra/scripts/remove-runsettings.sh 28 | windows: 29 | interactive: true 30 | shell: pwsh 31 | run: ./infra/scripts/remove-runsettings.ps1 32 | 33 | services: 34 | todoservice: 35 | language: csharp 36 | project: ./samples/datasync-server/src/Sample.Datasync.Server 37 | host: appservice 38 | -------------------------------------------------------------------------------- /docs/css/extra.css: -------------------------------------------------------------------------------- 1 | .wy-nav-content { 2 | max-width: 1200px !important; 3 | } -------------------------------------------------------------------------------- /docs/in-depth/server/db/in-memory.md: -------------------------------------------------------------------------------- 1 | # In-memory data store 2 | 3 | The in-memory store uses an internal dictionary to store the entities. This is useful for testing and for static data that is only refreshed when the server is updated. 4 | 5 | ## Set up 6 | 7 | You can create an in-memory repository with no persistent storage by adding a singleton service for the repository in your `Program.cs`: 8 | 9 | IEnumerable seedData = GenerateSeedData(); 10 | builder.Services.AddSingleton>(new InMemoryRepository(seedData)); 11 | 12 | Set up your table controller as follows: 13 | 14 | [Route("tables/[controller]")] 15 | public class ModelController : TableController 16 | { 17 | public MovieController(IRepository repository) : base(repository) 18 | { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docs/tutorial/server/img/2024-11-01-image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/docs/tutorial/server/img/2024-11-01-image1.png -------------------------------------------------------------------------------- /docs/tutorial/server/img/2024-11-01-image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/docs/tutorial/server/img/2024-11-01-image2.png -------------------------------------------------------------------------------- /docs/tutorial/server/img/2024-11-22-image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/docs/tutorial/server/img/2024-11-22-image1.png -------------------------------------------------------------------------------- /docs/tutorial/server/img/2024-11-22-image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/docs/tutorial/server/img/2024-11-22-image2.png -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/icon.png -------------------------------------------------------------------------------- /infra/main.parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "environmentName": { 6 | "value": "${AZURE_ENV_NAME}" 7 | }, 8 | "location": { 9 | "value": "${AZURE_LOCATION}" 10 | }, 11 | "principalId": { 12 | "value": "${AZURE_PRINCIPAL_ID}" 13 | }, 14 | "sqlAdminUsername": { 15 | "value": "appadmin" 16 | }, 17 | "sqlAdminPassword": { 18 | "value": "$(secretOrRandomPassword)" 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /infra/scripts/remove-runsettings.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | This scripts writes a suitable runsettings file for the tests so that 4 | the tests use the appropriate services for live testing. 5 | #> 6 | $outputFile = "tests\.runsettings" 7 | 8 | if (Test-Path $outputFile) { 9 | Remove-Item -Path $outputFile 10 | } else { 11 | Write-Output "File $($outputFile) does not exist." 12 | } 13 | -------------------------------------------------------------------------------- /infra/scripts/write-runsettings.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | This scripts writes a suitable runsettings file for the tests so that 4 | the tests use the appropriate services for live testing. 5 | #> 6 | $outputs = (azd env get-values --output json | ConvertFrom-Json) 7 | $outputFile = "tests\.runsettings" 8 | 9 | $prefix = @" 10 | 11 | 12 | 13 | 14 | 15 | "@ 16 | 17 | $postfix = @" 18 | true 19 | 20 | 21 | 22 | "@ 23 | 24 | $sb = New-Object System.Text.StringBuilder 25 | $outputs | Get-Member -MemberType Properties | Foreach-Object { 26 | $propertyName = $_.Name 27 | $propertyValue = [System.Security.SecurityElement]::Escape($outputs.$propertyName) 28 | $sb.AppendLine(" <$($propertyName)>$($propertyValue)") | Out-Null 29 | } 30 | 31 | $prefix + $sb.ToString() + $postfix | Out-File -FilePath $outputFile 32 | -------------------------------------------------------------------------------- /mkdocs.production.yml: -------------------------------------------------------------------------------- 1 | INHERIT: ./mkdocs.shared.yml 2 | site_name: Datasync Community Toolkit 3 | site_url: https://CommunityToolkit.github.io/Datasync/ 4 | repo_url: https://github.com/CommunityToolkit/Datasync/ 5 | repo_name: GitHub 6 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | INHERIT: ./mkdocs.shared.yml 2 | site_name: Datasync Community Toolkit 3 | dev_addr: localhost:7000 4 | -------------------------------------------------------------------------------- /samples/Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | false 5 | false 6 | 7 | -------------------------------------------------------------------------------- /samples/datasync-server-cosmosdb-singlecontainer/azure.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json 2 | 3 | name: community-toolkit-datasync-server 4 | metadata: 5 | template: community-toolkit-datasync-server@8.0.0 6 | 7 | workflows: 8 | up: 9 | steps: 10 | - azd: provision 11 | - azd: deploy --all 12 | 13 | services: 14 | backend: 15 | project: ./src 16 | language: csharp 17 | host: appservice -------------------------------------------------------------------------------- /samples/datasync-server-cosmosdb-singlecontainer/infra/main.parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "environmentName": { 6 | "value": "${AZURE_ENV_NAME}" 7 | }, 8 | "location": { 9 | "value": "${AZURE_LOCATION}" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /samples/datasync-server-cosmosdb-singlecontainer/src/Controllers/TodoItemController.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Sample.Datasync.Server.SingleContainer.Models; 8 | 9 | namespace Sample.Datasync.Server.Controllers; 10 | 11 | [Route("tables/[controller]")] 12 | public class TodoItemController : TableController 13 | { 14 | public TodoItemController(IRepository repository) 15 | : base(repository) 16 | { 17 | } 18 | } -------------------------------------------------------------------------------- /samples/datasync-server-cosmosdb-singlecontainer/src/Controllers/TodoListController.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Sample.Datasync.Server.SingleContainer.Models; 8 | 9 | namespace Sample.Datasync.Server.Controllers; 10 | 11 | [Route("tables/[controller]")] 12 | public class TodoListController : TableController 13 | { 14 | public TodoListController(IRepository repository) : base(repository) 15 | { 16 | Options = new TableControllerOptions { EnableSoftDelete = true }; 17 | } 18 | } -------------------------------------------------------------------------------- /samples/datasync-server-cosmosdb-singlecontainer/src/Models/TodoItem.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server.CosmosDb; 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | namespace Sample.Datasync.Server.SingleContainer.Models; 9 | 10 | public class TodoItem : CosmosTableData 11 | { 12 | [Required, MinLength(1)] 13 | public string Title { get; set; } = string.Empty; 14 | 15 | public bool IsComplete { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /samples/datasync-server-cosmosdb-singlecontainer/src/Models/TodoList.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server.CosmosDb; 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | namespace Sample.Datasync.Server.SingleContainer.Models; 9 | 10 | public class TodoList : CosmosTableData 11 | { 12 | [Required, MinLength(1)] 13 | public string Title { get; set; } = string.Empty; 14 | 15 | public string? ListId { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /samples/datasync-server-cosmosdb-singlecontainer/src/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "http": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": false, 8 | "applicationUrl": "http://localhost:5024", 9 | "environmentVariables": { 10 | "ASPNETCORE_ENVIRONMENT": "Development" 11 | } 12 | }, 13 | "https": { 14 | "commandName": "Project", 15 | "dotnetRunMessages": true, 16 | "launchBrowser": false, 17 | "applicationUrl": "https://localhost:7284;http://localhost:5024", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /samples/datasync-server-cosmosdb-singlecontainer/src/Sample.Datasync.Server.SingleContainer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | 4fb4ad03-5b6a-43b8-8e71-90b9d8252f94 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /samples/datasync-server-cosmosdb-singlecontainer/src/Sample.Datasync.Server.SingleContainer.http: -------------------------------------------------------------------------------- 1 | @Sample.Datasync.Server.SingleContainer_HostAddress = https://localhost:7284 2 | 3 | POST {{Sample.Datasync.Server.SingleContainer_HostAddress}}/tables/TodoItem 4 | Content-Type: application/json 5 | 6 | { 7 | "id": "2", 8 | "title": "Second item", 9 | "isComplete": false 10 | } 11 | 12 | ### 13 | 14 | GET {{Sample.Datasync.Server.SingleContainer_HostAddress}}/tables/TodoItem 15 | Accept: application/json 16 | 17 | ### 18 | 19 | POST {{Sample.Datasync.Server.SingleContainer_HostAddress}}/tables/TodoList 20 | Content-Type: application/json 21 | 22 | { 23 | "id": "1", 24 | "title": "First List", 25 | "listId": "My List" 26 | } 27 | 28 | ### 29 | 30 | GET {{Sample.Datasync.Server.SingleContainer_HostAddress}}/tables/TodoList 31 | Accept: application/json 32 | 33 | ### -------------------------------------------------------------------------------- /samples/datasync-server-cosmosdb-singlecontainer/src/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /samples/datasync-server-cosmosdb-singlecontainer/src/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /samples/datasync-server/azure.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json 2 | 3 | name: community-toolkit-datasync-server 4 | metadata: 5 | template: community-toolkit-datasync-server@8.0.0 6 | 7 | workflows: 8 | up: 9 | steps: 10 | - azd: provision 11 | - azd: deploy --all 12 | 13 | services: 14 | backend: 15 | project: ./src/Sample.Datasync.Server 16 | language: csharp 17 | host: appservice -------------------------------------------------------------------------------- /samples/datasync-server/infra/main.parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "environmentName": { 6 | "value": "${AZURE_ENV_NAME}" 7 | }, 8 | "location": { 9 | "value": "${AZURE_LOCATION}" 10 | }, 11 | "principalId": { 12 | "value": "${AZURE_PRINCIPAL_ID}" 13 | }, 14 | "sqlAdminUsername": { 15 | "value": "appadmin" 16 | }, 17 | "sqlAdminPassword": { 18 | "value": "$(secretOrRandomPassword)" 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /samples/datasync-server/src/Sample.Datasync.Server/Controllers/TodoItemController.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server; 6 | using CommunityToolkit.Datasync.Server.EntityFrameworkCore; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Sample.Datasync.Server.Db; 9 | 10 | namespace Sample.Datasync.Server.Controllers; 11 | 12 | [Route("tables/[controller]")] 13 | public class TodoItemController : TableController 14 | { 15 | public TodoItemController(AppDbContext context) 16 | : base(new EntityTableRepository(context)) 17 | { 18 | } 19 | } -------------------------------------------------------------------------------- /samples/datasync-server/src/Sample.Datasync.Server/Controllers/TodoListController.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server; 6 | using CommunityToolkit.Datasync.Server.EntityFrameworkCore; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Sample.Datasync.Server.Db; 9 | 10 | namespace Sample.Datasync.Server.Controllers; 11 | 12 | [Route("tables/[controller]")] 13 | public class TodoListController : TableController 14 | { 15 | public TodoListController(AppDbContext context) : base(new EntityTableRepository(context)) 16 | { 17 | Options = new TableControllerOptions { EnableSoftDelete = true }; 18 | } 19 | } -------------------------------------------------------------------------------- /samples/datasync-server/src/Sample.Datasync.Server/Db/TodoItem.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server.EntityFrameworkCore; 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | namespace Sample.Datasync.Server.Db; 9 | 10 | public class TodoItem : EntityTableData 11 | { 12 | [Required, MinLength(1)] 13 | public string Title { get; set; } = string.Empty; 14 | 15 | public bool IsComplete { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /samples/datasync-server/src/Sample.Datasync.Server/Db/TodoList.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server.EntityFrameworkCore; 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | namespace Sample.Datasync.Server.Db; 9 | 10 | public class TodoList : EntityTableData 11 | { 12 | [Required, MinLength(1)] 13 | public string Title { get; set; } = string.Empty; 14 | 15 | public string? ListId { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /samples/datasync-server/src/Sample.Datasync.Server/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "https": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "launchUrl": "tables/todoitem", 9 | "applicationUrl": "https://localhost:5001", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | }, 13 | "sqlDebugging": true 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/datasync-server/src/Sample.Datasync.Server/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "Swagger": { 9 | "Driver": "net9" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/datasync-server/src/Sample.Datasync.Server/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoApp;Trusted_Connection=True" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Information", 8 | "Microsoft.AspNetCore": "Warning" 9 | } 10 | }, 11 | "AllowedHosts": "*" 12 | } 13 | -------------------------------------------------------------------------------- /samples/todoapp-mvc/TodoApp.Service/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace TodoApp.Service.Controllers; 4 | 5 | public class HomeController : Controller 6 | { 7 | public IActionResult Index() 8 | { 9 | return View(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/todoapp-mvc/TodoApp.Service/Controllers/TodoItemsController.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Datasync.Server; 2 | using CommunityToolkit.Datasync.Server.EntityFrameworkCore; 3 | using Microsoft.AspNetCore.Mvc; 4 | using TodoApp.Service.Database; 5 | 6 | namespace TodoApp.Service.Controllers; 7 | 8 | [Route("tables/todoitems")] 9 | public class TodoItemsController : TableController 10 | { 11 | public TodoItemsController(TodoContext context) : base() 12 | { 13 | Repository = new EntityTableRepository(context); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/todoapp-mvc/TodoApp.Service/Database/TodoContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | 3 | namespace TodoApp.Service.Database; 4 | 5 | public class TodoContext(DbContextOptions options) : DbContext(options) 6 | { 7 | public DbSet TodoItems => Set(); 8 | 9 | public async Task InitializeDatabaseAsync() 10 | { 11 | await Database.EnsureDeletedAsync(); 12 | await Database.EnsureCreatedAsync(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /samples/todoapp-mvc/TodoApp.Service/Database/TodoItem.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Datasync.Server.EntityFrameworkCore; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace TodoApp.Service.Database; 5 | 6 | public class TodoItem : EntityTableData 7 | { 8 | [Required, StringLength(255, MinimumLength = 1)] 9 | public string Title { get; set; } = string.Empty; 10 | public bool Completed { get; set; } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /samples/todoapp-mvc/TodoApp.Service/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "http": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "launchUrl": "", 9 | "applicationUrl": "http://localhost:5289", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | }, 14 | "https": { 15 | "commandName": "Project", 16 | "dotnetRunMessages": true, 17 | "launchBrowser": true, 18 | "launchUrl": "", 19 | "applicationUrl": "https://localhost:7133;http://localhost:5289", 20 | "environmentVariables": { 21 | "ASPNETCORE_ENVIRONMENT": "Development" 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/todoapp-mvc/TodoApp.Service/TodoApp.Service.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /samples/todoapp-mvc/TodoApp.Service/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | string title = ViewBag.Title ?? ViewData["Title"] as string ?? "TodoMVC with Datasync API"; 3 | } 4 | 5 | 6 | 7 | 8 | 9 | 10 | @title 11 | @RenderSection("Stylesheets", required: false) 12 | 13 | 14 | @RenderBody() 15 | 16 |
17 | @RenderSection("Scripts", required: false) 18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /samples/todoapp-mvc/TodoApp.Service/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers -------------------------------------------------------------------------------- /samples/todoapp-mvc/TodoApp.Service/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /samples/todoapp-mvc/TodoApp.Service/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoApp;Trusted_Connection=True" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Information", 8 | "Microsoft.AspNetCore": "Warning" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /samples/todoapp-mvc/TodoApp.Service/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /samples/todoapp-mvc/TodoApp.Service/libman.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "defaultProvider": "jsdelivr", 4 | "libraries": [ 5 | { 6 | "provider": "jsdelivr", 7 | "library": "todomvc-app-css@2.4.3", 8 | "destination": "wwwroot/lib/todomvc-app-css/" 9 | }, 10 | { 11 | "provider": "jsdelivr", 12 | "library": "todomvc-common@1.0.5", 13 | "destination": "wwwroot/lib/todomvc-common/" 14 | }, 15 | { 16 | "provider": "jsdelivr", 17 | "library": "jquery@3.7.1", 18 | "destination": "wwwroot/lib/jquery/" 19 | }, 20 | { 21 | "provider": "jsdelivr", 22 | "library": "handlebars@4.7.8", 23 | "destination": "wwwroot/lib/handlebars/" 24 | } 25 | , 26 | { 27 | "provider": "jsdelivr", 28 | "library": "director@1.2.8", 29 | "destination": "wwwroot/lib/director/" 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /samples/todoapp-mvc/TodoApp.Service/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | #main, #footer { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /samples/todoapp-mvc/part5.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31903.59 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TodoApp.Service", "TodoApp.Service\TodoApp.Service.csproj", "{660AE926-DAA0-4A9A-99CD-F30FB096723D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {660AE926-DAA0-4A9A-99CD-F30FB096723D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {660AE926-DAA0-4A9A-99CD-F30FB096723D}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {660AE926-DAA0-4A9A-99CD-F30FB096723D}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {660AE926-DAA0-4A9A-99CD-F30FB096723D}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly:ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/ClientApp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net9.0-windows 6 | enable 7 | enable 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Always 24 | 25 | 26 | Always 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/Converters/BooleanToImageConverter.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Globalization; 6 | using System.Windows.Data; 7 | using System.Windows.Media.Imaging; 8 | 9 | namespace ClientApp.Converters; 10 | 11 | /// 12 | /// A converter to convert the boolean for IsComplete into one of two images. 13 | /// 14 | public class BooleanToImageConverter : IValueConverter 15 | { 16 | private const string baseUri = "pack://application:,,,/Images"; 17 | 18 | public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | if (value is bool booleanValue) 21 | { 22 | return new BitmapImage(new Uri(booleanValue ? $"{baseUri}/completed.png" : $"{baseUri}/incomplete.png")); 23 | } 24 | 25 | return null; 26 | } 27 | 28 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 29 | { 30 | throw new NotImplementedException(); 31 | } 32 | } -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/Images/completed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp-tutorial/ClientApp/Images/completed.png -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/Images/incomplete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp-tutorial/ClientApp/Images/incomplete.png -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/Interfaces/IAlertService.cs: -------------------------------------------------------------------------------- 1 | namespace ClientApp.Interfaces; 2 | 3 | /// 4 | /// An interface for displaying alerts to the user. 5 | /// 6 | public interface IAlertService 7 | { 8 | Task ShowErrorAlertAsync(string title, string message = "", string cancel = "OK"); 9 | Task ShowInfoAlertAsync(string title, string message = "", string cancel = "OK"); 10 | } -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/Interfaces/IAppInitializer.cs: -------------------------------------------------------------------------------- 1 | namespace ClientApp.Interfaces; 2 | 3 | /// 4 | /// Service definition for the application intiializer. 5 | /// 6 | public interface IAppInitializer 7 | { 8 | Task Initialize(); 9 | } -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/Interfaces/ITodoService.cs: -------------------------------------------------------------------------------- 1 | using ClientApp.Models; 2 | 3 | namespace ClientApp.Interfaces; 4 | 5 | /// 6 | /// Service definition for the TodoItem service. 7 | /// 8 | public interface ITodoService 9 | { 10 | Task GetTodoItemAsync(string id, CancellationToken cancellationToken = default); 11 | Task> GetAllTodoItemsAsync(CancellationToken cancellationToken = default); 12 | Task AddTodoItemAsync(string title, CancellationToken cancellationToken = default); 13 | Task ReplaceTodoItemAsync(TodoItem updatedItem, CancellationToken cancellationToken = default); 14 | } -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using ClientApp.Models; 2 | using ClientApp.ViewModels; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using System.Windows.Input; 6 | 7 | namespace ClientApp; 8 | 9 | /// 10 | /// Interaction logic for MainWindow.xaml 11 | /// 12 | public partial class MainWindow : Window 13 | { 14 | private readonly TodoListViewModel viewModel; 15 | 16 | public MainWindow() 17 | { 18 | InitializeComponent(); 19 | this.viewModel = App.GetRequiredService(); 20 | DataContext = this.viewModel; 21 | } 22 | 23 | protected void ListViewItem_DoubleClickEventHandler(object sender, MouseButtonEventArgs e) 24 | { 25 | TodoItem? item = ((ListViewItem)sender).Content as TodoItem; 26 | this.viewModel.UpdateItemCommand.Execute(item); 27 | } 28 | } -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/Models/OfflineClientEntity.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace ClientApp.Models; 4 | 5 | public abstract class OfflineClientEntity 6 | { 7 | [Key] 8 | public string Id { get; set; } = Guid.NewGuid().ToString("N"); 9 | 10 | public DateTimeOffset? UpdatedAt { get; set; } 11 | public string? Version { get; set; } 12 | public bool Deleted { get; set; } 13 | } -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/Models/TodoItem.cs: -------------------------------------------------------------------------------- 1 | namespace ClientApp.Models; 2 | 3 | public class TodoItem : OfflineClientEntity, IEquatable 4 | { 5 | public string Title { get; set; } = string.Empty; 6 | public bool IsComplete { get; set; } 7 | 8 | public bool Equals(TodoItem? other) 9 | => other is not null && Id == other.Id && Version == other.Version; 10 | } -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/Services/AlertService.cs: -------------------------------------------------------------------------------- 1 | using ClientApp.Interfaces; 2 | using System.Windows; 3 | 4 | namespace ClientApp.Services; 5 | 6 | public class AlertService : IAlertService 7 | { 8 | public Task ShowErrorAlertAsync(string title, string message = "", string cancel = "OK") 9 | { 10 | _ = MessageBox.Show( 11 | messageBoxText: string.IsNullOrEmpty(message) ? title : message, 12 | caption: title, 13 | button: MessageBoxButton.OK, 14 | icon: MessageBoxImage.Error); 15 | return Task.CompletedTask; 16 | } 17 | 18 | public Task ShowInfoAlertAsync(string title, string message = "", string cancel = "OK") 19 | { 20 | _ = MessageBox.Show( 21 | messageBoxText: string.IsNullOrEmpty(message) ? title : message, 22 | caption: title, 23 | button: MessageBoxButton.OK, 24 | icon: MessageBoxImage.Information); 25 | return Task.CompletedTask; 26 | } 27 | } -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ClientApp/Services/AppInitializer.cs: -------------------------------------------------------------------------------- 1 | using ClientApp.Interfaces; 2 | 3 | namespace ClientApp.Services; 4 | 5 | public class AppInitializer : IAppInitializer 6 | { 7 | public Task Initialize() 8 | { 9 | return Task.CompletedTask; 10 | } 11 | } -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ServerApp/Controllers/TodoItemController.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Datasync.Server; 2 | using Microsoft.AspNetCore.Mvc; 3 | using ServerApp.Models; 4 | 5 | namespace ServerApp.Controllers; 6 | 7 | [Route("tables/todoitem")] 8 | public class TodoItemController(IRepository repository) : TableController(repository) 9 | { 10 | } -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ServerApp/Models/TodoItem.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Datasync.Server.InMemory; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace ServerApp.Models; 5 | 6 | public class TodoItem : InMemoryTableData, IEquatable 7 | { 8 | [Required, StringLength(255, MinimumLength = 1)] 9 | public string Title { get; set; } = string.Empty; 10 | 11 | public bool IsComplete { get; set; } 12 | 13 | public bool Equals(TodoItem? other) 14 | => other is not null && Id == other.Id && Version.SequenceEqual(other.Version); 15 | } -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ServerApp/Program.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Datasync.Server; 2 | using CommunityToolkit.Datasync.Server.InMemory; 3 | using ServerApp.Models; 4 | 5 | var builder = WebApplication.CreateBuilder(args); 6 | 7 | builder.Services.AddSingleton, InMemoryRepository>(); 8 | builder.Services.AddDatasyncServices(); 9 | builder.Services.AddControllers(); 10 | 11 | var app = builder.Build(); 12 | 13 | app.UseHttpsRedirection(); 14 | app.UseAuthorization(); 15 | app.MapControllers(); 16 | 17 | app.Run(); 18 | -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ServerApp/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:33641", 8 | "sslPort": 44330 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "applicationUrl": "http://localhost:5274", 17 | "environmentVariables": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | } 20 | }, 21 | "https": { 22 | "commandName": "Project", 23 | "dotnetRunMessages": true, 24 | "launchBrowser": true, 25 | "applicationUrl": "https://localhost:7181;http://localhost:5274", 26 | "environmentVariables": { 27 | "ASPNETCORE_ENVIRONMENT": "Development" 28 | } 29 | }, 30 | "IIS Express": { 31 | "commandName": "IISExpress", 32 | "launchBrowser": true, 33 | "environmentVariables": { 34 | "ASPNETCORE_ENVIRONMENT": "Development" 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ServerApp/ServerApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ServerApp/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft.AspNetCore": "Warning" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ServerApp/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ServerApp/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-size: 14px; 3 | } 4 | 5 | @media (min-width: 768px) { 6 | html { 7 | font-size: 16px; 8 | } 9 | } 10 | 11 | .btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus { 12 | box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb; 13 | } 14 | 15 | html { 16 | position: relative; 17 | min-height: 100%; 18 | } 19 | 20 | body { 21 | margin-bottom: 60px; 22 | } 23 | 24 | .form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder { 25 | color: var(--bs-secondary-color); 26 | text-align: end; 27 | } 28 | 29 | .form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder { 30 | text-align: start; 31 | } -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ServerApp/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp-tutorial/ServerApp/wwwroot/favicon.ico -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ServerApp/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | // for details on configuring this project to bundle and minify static web assets. 3 | 4 | // Write your JavaScript code. 5 | -------------------------------------------------------------------------------- /samples/todoapp-tutorial/ServerApp/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Copyright OpenJS Foundation and other contributors, https://openjsf.org/ 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | enable 4 | 11.2.3 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.Android/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.Android/Icon.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.Android/MainActivity.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Content.PM; 3 | using Avalonia; 4 | using Avalonia.Android; 5 | 6 | namespace TodoApp.Avalonia.Android; 7 | 8 | [Activity( 9 | Label = "TodoApp.Avalonia.Android", 10 | Theme = "@style/MyTheme.NoActionBar", 11 | Icon = "@drawable/icon", 12 | MainLauncher = true, 13 | ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)] 14 | public class MainActivity : AvaloniaMainActivity 15 | { 16 | protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) 17 | { 18 | return base.CustomizeAppBuilder(builder) 19 | .WithInterFont(); 20 | } 21 | } -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.Android/Properties/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.Android/Resources/drawable/splash_screen.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.Android/Resources/values-night/colors.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | #212121 4 | 5 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.Android/Resources/values-v31/styles.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 6 | 7 | 17 | 21 | 22 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.Android/Resources/values/colors.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | #FFFFFF 4 | 5 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.Android/Resources/values/styles.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.Desktop/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia; 3 | 4 | namespace TodoApp.Avalonia.Desktop; 5 | 6 | sealed class Program 7 | { 8 | // Initialization code. Don't use any Avalonia, third-party APIs or any 9 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 10 | // yet and stuff might break. 11 | [STAThread] 12 | public static void Main(string[] args) => BuildAvaloniaApp() 13 | .StartWithClassicDesktopLifetime(args); 14 | 15 | // Avalonia configuration, don't remove; also used by visual designer. 16 | public static AppBuilder BuildAvaloniaApp() 17 | => AppBuilder.Configure() 18 | .UsePlatformDetect() 19 | .WithInterFont() 20 | .LogToTrace(); 21 | } -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.Desktop/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.iOS/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | using Foundation; 2 | using UIKit; 3 | using Avalonia; 4 | using Avalonia.Controls; 5 | using Avalonia.iOS; 6 | using Avalonia.Media; 7 | 8 | namespace TodoApp.Avalonia.iOS; 9 | 10 | // The UIApplicationDelegate for the application. This class is responsible for launching the 11 | // User Interface of the application, as well as listening (and optionally responding) to 12 | // application events from iOS. 13 | [Register("AppDelegate")] 14 | #pragma warning disable CA1711 // Identifiers should not have incorrect suffix 15 | public partial class AppDelegate : AvaloniaAppDelegate 16 | #pragma warning restore CA1711 // Identifiers should not have incorrect suffix 17 | { 18 | protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) 19 | { 20 | return base.CustomizeAppBuilder(builder) 21 | .WithInterFont(); 22 | } 23 | } -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.iOS/Entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.iOS/Main.cs: -------------------------------------------------------------------------------- 1 | using UIKit; 2 | 3 | namespace TodoApp.Avalonia.iOS; 4 | 5 | public class Application 6 | { 7 | // This is the main entry point of the application. 8 | static void Main(string[] args) 9 | { 10 | // if you want to use a different Application Delegate class from "AppDelegate" 11 | // you can specify it here. 12 | UIApplication.Main(args, null, typeof(AppDelegate)); 13 | } 14 | } -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.iOS/TodoApp.Avalonia.iOS.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | Exe 4 | net9.0-ios 5 | 15.0 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia/Assets/avalonia-logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia/Assets/avalonia-logo.ico -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia/Database/IDbInitializer.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace TodoApp.Avalonia.Database; 9 | 10 | /// 11 | /// An interface to initialize a database. 12 | /// 13 | public interface IDbInitializer 14 | { 15 | /// 16 | /// Synchronously initialize the database. 17 | /// 18 | void Initialize(); 19 | 20 | /// 21 | /// Asynchronously initialize the database. 22 | /// 23 | /// A to observe. 24 | /// A task that resolves when complete. 25 | Task InitializeAsync(CancellationToken cancellationToken = default); 26 | } 27 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia/Database/ToDoItem.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace TodoApp.Avalonia.Database; 6 | 7 | public class TodoItem : OfflineClientEntity 8 | { 9 | /// 10 | /// Gets or sets the content. 11 | /// 12 | public string Title { get; set; } = string.Empty; 13 | 14 | /// 15 | /// Gets or sets if the task was completed. 16 | /// 17 | public bool IsComplete { get; set; } = false; 18 | } 19 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia/Services/IDialogBus.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace TodoApp.Avalonia.Services; 6 | 7 | /// 8 | /// This interface is used to indicate that a class can be used to communicate with the View 9 | /// 10 | public interface IDialogBus 11 | { 12 | 13 | } -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia/Services/INotificationService.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Avalonia.Controls.Notifications; 6 | 7 | namespace TodoApp.Avalonia.Services; 8 | 9 | /// 10 | /// An interface which a View needs to implement in order to show Notifications sent from any 11 | /// 12 | public interface INotificationService 13 | { 14 | /// 15 | /// Gets the NotificationManager which is used to display a NotificationMessage 16 | /// 17 | public WindowNotificationManager NotificationManager { get; } 18 | } -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia/ViewModels/DesignTimeViewModels.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using Avalonia; 7 | using Microsoft.Extensions.DependencyInjection; 8 | 9 | namespace TodoApp.Avalonia.ViewModels; 10 | #if DEBUG 11 | 12 | /// 13 | /// Holds some sample ViewModels to be shown in the Designer. 14 | /// 15 | public static class DesignTimeViewModels 16 | { 17 | public static TodoListViewModel TodoListDesignerViewModel => 18 | (Application.Current as App)?.Services.GetRequiredService() ?? throw new InvalidOperationException(); 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | 3 | namespace TodoApp.Avalonia.ViewModels; 4 | 5 | public abstract class ViewModelBase : ObservableObject 6 | { 7 | } -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia/Views/MainWindow.axaml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia/Views/MainWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace TodoApp.Avalonia.Views; 4 | 5 | public partial class MainWindow : Window 6 | { 7 | public MainWindow() 8 | { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/App.xaml: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/AppShell.xaml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/AppShell.xaml.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace TodoApp.MAUI; 6 | 7 | public partial class AppShell : Shell 8 | { 9 | public AppShell() 10 | { 11 | InitializeComponent(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/MauiProgram.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace TodoApp.MAUI; 8 | public static class MauiProgram 9 | { 10 | public static MauiApp CreateMauiApp() 11 | { 12 | var builder = MauiApp.CreateBuilder(); 13 | builder 14 | .UseMauiApp() 15 | .ConfigureFonts(fonts => 16 | { 17 | fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); 18 | fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); 19 | }); 20 | 21 | #if DEBUG 22 | builder.Logging.AddDebug(); 23 | #endif 24 | 25 | return builder.Build(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Models/IDbInitializer.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace TodoApp.MAUI.Models; 6 | 7 | /// 8 | /// An interface to initialize a database. 9 | /// 10 | public interface IDbInitializer 11 | { 12 | /// 13 | /// Synchronously initialize the database. 14 | /// 15 | void Initialize(); 16 | 17 | /// 18 | /// Asynchronously initialize the database. 19 | /// 20 | /// A to observe. 21 | /// A task that resolves when complete. 22 | Task InitializeAsync(CancellationToken cancellationToken = default); 23 | } 24 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Models/OfflineClientEntity.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.ComponentModel.DataAnnotations; 6 | 7 | namespace TodoApp.MAUI.Models; 8 | 9 | /// 10 | /// An abstract class for working with offline entities. 11 | /// 12 | public abstract class OfflineClientEntity 13 | { 14 | [Key] 15 | public string Id { get; set; } = Guid.NewGuid().ToString("N"); 16 | public DateTimeOffset? UpdatedAt { get; set; } 17 | public string? Version { get; set; } 18 | public bool Deleted { get; set; } 19 | } 20 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Models/TodoItem.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace TodoApp.MAUI.Models; 6 | 7 | public class TodoItem : OfflineClientEntity 8 | { 9 | public string Title { get; set; } = string.Empty; 10 | public bool IsComplete { get; set; } = false; 11 | } 12 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Platforms/Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Platforms/Android/MainActivity.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Android.App; 6 | using Android.Content.PM; 7 | using Android.OS; 8 | 9 | namespace TodoApp.MAUI; 10 | [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] 11 | public class MainActivity : MauiAppCompatActivity 12 | { 13 | } 14 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Platforms/Android/MainApplication.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Android.App; 6 | using Android.Runtime; 7 | 8 | namespace TodoApp.MAUI; 9 | [Application] 10 | public class MainApplication : MauiApplication 11 | { 12 | public MainApplication(IntPtr handle, JniHandleOwnership ownership) 13 | : base(handle, ownership) 14 | { 15 | } 16 | 17 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 18 | } 19 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Platforms/Android/Resources/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #512BD4 4 | #2B0B98 5 | #2B0B98 6 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Platforms/Windows/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Platforms/Windows/App.xaml.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.UI.Xaml; 6 | 7 | // To learn more about WinUI, the WinUI project structure, 8 | // and more about our project templates, see: http://aka.ms/winui-project-info. 9 | 10 | namespace TodoApp.MAUI.WinUI; 11 | /// 12 | /// Provides application-specific behavior to supplement the default Application class. 13 | /// 14 | public partial class App : MauiWinUIApplication 15 | { 16 | /// 17 | /// Initializes the singleton application object. This is the first line of authored code 18 | /// executed, and as such is the logical equivalent of main() or WinMain(). 19 | /// 20 | public App() 21 | { 22 | this.InitializeComponent(); 23 | } 24 | 25 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Platforms/Windows/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | true/PM 12 | PerMonitorV2, PerMonitor 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Platforms/iOS/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Foundation; 6 | 7 | namespace TodoApp.MAUI; 8 | [Register("AppDelegate")] 9 | public class AppDelegate : MauiUIApplicationDelegate 10 | { 11 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 12 | } 13 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Platforms/iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LSRequiresIPhoneOS 6 | 7 | UIDeviceFamily 8 | 9 | 1 10 | 2 11 | 12 | UIRequiredDeviceCapabilities 13 | 14 | arm64 15 | 16 | UISupportedInterfaceOrientations 17 | 18 | UIInterfaceOrientationPortrait 19 | UIInterfaceOrientationLandscapeLeft 20 | UIInterfaceOrientationLandscapeRight 21 | 22 | UISupportedInterfaceOrientations~ipad 23 | 24 | UIInterfaceOrientationPortrait 25 | UIInterfaceOrientationPortraitUpsideDown 26 | UIInterfaceOrientationLandscapeLeft 27 | UIInterfaceOrientationLandscapeRight 28 | 29 | XSAppIconAssets 30 | Assets.xcassets/appicon.appiconset 31 | 32 | 33 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Platforms/iOS/Program.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using ObjCRuntime; 6 | using UIKit; 7 | 8 | namespace TodoApp.MAUI; 9 | public class Program 10 | { 11 | // This is the main entry point of the application. 12 | static void Main(string[] args) 13 | { 14 | // if you want to use a different Application Delegate class from "AppDelegate" 15 | // you can specify it here. 16 | UIApplication.Main(args, null, typeof(AppDelegate)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Windows Machine": { 4 | "commandName": "Project", 5 | "nativeDebugging": false 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Resources/AppIcon/appicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Resources/Fonts/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.MAUI/Resources/Fonts/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Resources/Fonts/OpenSans-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.MAUI/Resources/Fonts/OpenSans-Semibold.ttf -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Resources/Images/additem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.MAUI/Resources/Images/additem.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Resources/Images/completed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.MAUI/Resources/Images/completed.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Resources/Images/dotnet_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.MAUI/Resources/Images/dotnet_bot.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Resources/Images/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.MAUI/Resources/Images/refresh.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Resources/Raw/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | Any raw assets you want to be deployed with your application can be placed in 2 | this directory (and child directories). Deployment of the asset to your application 3 | is automatically handled by the following `MauiAsset` Build Action within your `.csproj`. 4 | 5 | 6 | 7 | These files will be deployed with your package and will be accessible using Essentials: 8 | 9 | async Task LoadMauiAsset() 10 | { 11 | using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); 12 | using var reader = new StreamReader(stream); 13 | 14 | var contents = reader.ReadToEnd(); 15 | } 16 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Services/AlertService.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace TodoApp.MAUI.Services; 6 | public interface IAlertService 7 | { 8 | Task ShowErrorAlertAsync(string title, string message, string cancel = "OK"); 9 | } 10 | 11 | public class AlertService : IAlertService 12 | { 13 | public Task ShowErrorAlertAsync(string title, string message, string cancel = "OK") 14 | => Application.Current!.Windows[0].Page!.DisplayAlert(title, message, cancel); 15 | } 16 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.MAUI/Services/SqliteHelper.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.Data.Sqlite; 6 | 7 | namespace TodoApp.MAUI.Services; 8 | 9 | internal sealed class SqliteHelper 10 | { 11 | private const string ConnectionString = "Data Source=:memory:"; 12 | private static readonly Lazy singleton = new(() => new SqliteHelper()); 13 | 14 | public static SqliteConnection Connection => singleton.Value.SqliteConnection; 15 | 16 | #region SqliteHelper Internals 17 | private SqliteHelper() 18 | { 19 | SqliteConnection = new SqliteConnection(ConnectionString); 20 | SqliteConnection.Open(); 21 | } 22 | 23 | private SqliteConnection SqliteConnection { get; } 24 | #endregion 25 | } 26 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/.run/Readme.md: -------------------------------------------------------------------------------- 1 | # About the `.run` folder 2 | 3 | This folder is present to add support for the [Rider IDE](https://aka.platform.uno/rider-getstarted). You can remove this folder safely if you're not using Rider. 4 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "unoplatform.vscode" 4 | ], 5 | } 6 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "explorer.fileNesting.enabled": true, 3 | "explorer.fileNesting.expand": false, 4 | "explorer.fileNesting.patterns": { 5 | "*.xaml": "$(capture).xaml.cs" 6 | }, 7 | "files.associations": { 8 | "global.json": "jsonc" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | enable 4 | enable 5 | true 6 | true 7 | 13 | $(NoWarn);NU1507;NETSDK1201;PRI257 14 | 15 | 16 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/Directory.Build.targets: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/App.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/AddItem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/AddItem.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Images/back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/RefreshItems.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/RefreshItems.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/SharedAssets.md: -------------------------------------------------------------------------------- 1 | # Shared Assets 2 | 3 | See documentation about assets here: https://github.com/unoplatform/uno/blob/master/doc/articles/features/working-with-assets.md 4 | 5 | ## Here is a cheat sheet 6 | 7 | 1. Add the image file to the `Assets` directory of a shared project. 8 | 2. Set the build action to `Content`. 9 | 3. (Recommended) Provide an asset for various scales/dpi 10 | 11 | ### Examples 12 | 13 | ```text 14 | \Assets\Images\logo.scale-100.png 15 | \Assets\Images\logo.scale-200.png 16 | \Assets\Images\logo.scale-400.png 17 | 18 | \Assets\Images\scale-100\logo.png 19 | \Assets\Images\scale-200\logo.png 20 | \Assets\Images\scale-400\logo.png 21 | ``` 22 | 23 | ### Table of scales 24 | 25 | | Scale | WinUI | iOS/MacCatalyst | Android | 26 | |-------|:-----------:|:---------------:|:-------:| 27 | | `100` | scale-100 | @1x | mdpi | 28 | | `125` | scale-125 | N/A | N/A | 29 | | `150` | scale-150 | N/A | hdpi | 30 | | `200` | scale-200 | @2x | xhdpi | 31 | | `300` | scale-300 | @3x | xxhdpi | 32 | | `400` | scale-400 | N/A | xxxhdpi | 33 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/StoreLogo.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.Uno/TodoApp.Uno/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/IDbInitializer.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace TodoApp.Uno.Database; 9 | 10 | /// 11 | /// An interface to initialize a database. 12 | /// 13 | public interface IDbInitializer 14 | { 15 | /// 16 | /// Synchronously initialize the database. 17 | /// 18 | void Initialize(); 19 | 20 | /// 21 | /// Asynchronously initialize the database. 22 | /// 23 | /// A to observe. 24 | /// A task that resolves when complete. 25 | Task InitializeAsync(CancellationToken cancellationToken = default); 26 | } 27 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/OfflineClientEntity.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | namespace TodoApp.Uno.Database; 9 | 10 | /// 11 | /// An abstract class for working with offline entities. 12 | /// 13 | public abstract class OfflineClientEntity 14 | { 15 | [System.ComponentModel.DataAnnotations.Key] 16 | public string Id { get; set; } 17 | public DateTimeOffset? UpdatedAt { get; set; } 18 | public string? Version { get; set; } 19 | public bool Deleted { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Database/TodoItem.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Text.Json; 6 | 7 | namespace TodoApp.Uno.Database; 8 | 9 | public class TodoItem : OfflineClientEntity 10 | { 11 | public string Title { get; set; } = string.Empty; 12 | public bool IsComplete { get; set; } = false; 13 | 14 | public override string ToString() 15 | => JsonSerializer.Serialize(this); 16 | } 17 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using System.Collections.Immutable; 2 | global using CommunityToolkit.Mvvm.ComponentModel; 3 | global using CommunityToolkit.Mvvm.Input; 4 | global using Microsoft.Extensions.DependencyInjection; 5 | global using Microsoft.Extensions.Hosting; 6 | global using Microsoft.Extensions.Localization; 7 | global using Microsoft.Extensions.Logging; 8 | global using Microsoft.Extensions.Options; 9 | global using TodoApp.Uno.Presentation; 10 | global using ApplicationExecutionState = Windows.ApplicationModel.Activation.ApplicationExecutionState; 11 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Package.appxmanifest: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Assets/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | To add cross-platform image assets for your Uno Platform app, use the Assets folder 2 | in the shared project instead. Assets in this folder are Android-only assets. 3 | 4 | Any raw assets you want to be deployed with your application can be placed in 5 | this directory (and child directories) and given a Build Action of "AndroidAsset". 6 | 7 | These files will be deployed with your package and will be accessible using Android's 8 | AssetManager, like this: 9 | 10 | public class ReadAsset : Activity 11 | { 12 | protected override void OnCreate (Bundle bundle) 13 | { 14 | base.OnCreate (bundle); 15 | 16 | InputStream input = Assets.Open ("my_asset.txt"); 17 | } 18 | } 19 | 20 | Additionally, some Android functions will automatically load asset files: 21 | 22 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); 23 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/MainActivity.Android.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Content.PM; 3 | using Android.OS; 4 | using Android.Views; 5 | using Android.Widget; 6 | 7 | namespace TodoApp.Uno.Droid; 8 | [Activity( 9 | MainLauncher = true, 10 | ConfigurationChanges = global::Uno.UI.ActivityHelper.AllConfigChanges, 11 | WindowSoftInputMode = SoftInput.AdjustNothing | SoftInput.StateHidden 12 | )] 13 | public class MainActivity : Microsoft.UI.Xaml.ApplicationActivity 14 | { 15 | } 16 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/values/Strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello World, Click Me! 4 | TodoApp.Uno 5 | 6 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/Resources/values/Styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Android/environment.conf: -------------------------------------------------------------------------------- 1 | # See this for more details: http://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/ 2 | MONO_GC_PARAMS=bridge-implementation=tarjan,nursery-size=32m,soft-heap-limit=256m -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/Desktop/Program.cs: -------------------------------------------------------------------------------- 1 | using Uno.UI.Runtime.Skia; 2 | 3 | namespace TodoApp.Uno; 4 | public class Program 5 | { 6 | [STAThread] 7 | public static void Main(string[] args) 8 | { 9 | var host = SkiaHostBuilder.Create() 10 | .App(() => new App()) 11 | .UseX11() 12 | .UseLinuxFrameBuffer() 13 | .UseMacOS() 14 | .UseWindows() 15 | .Build(); 16 | 17 | host.Run(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIDeviceFamily 6 | 7 | 2 8 | 9 | LSApplicationCategoryType 10 | public.app-category.utilities 11 | UISupportedInterfaceOrientations 12 | 13 | UIInterfaceOrientationPortrait 14 | UIInterfaceOrientationLandscapeLeft 15 | UIInterfaceOrientationLandscapeRight 16 | 17 | XSAppIconAssets 18 | Assets.xcassets/icon.appiconset 19 | 20 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/MacCatalyst/Main.maccatalyst.cs: -------------------------------------------------------------------------------- 1 | using UIKit; 2 | 3 | namespace TodoApp.Uno.MacCatalyst; 4 | public class EntryPoint 5 | { 6 | // This is the main entry point of the application. 7 | public static void Main(string[] args) 8 | { 9 | // if you want to use a different Application Delegate class from "AppDelegate" 10 | // you can specify it here. 11 | UIApplication.Main(args, null, typeof(App)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/LinkerConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/Program.cs: -------------------------------------------------------------------------------- 1 | namespace TodoApp.Uno; 2 | 3 | public class Program 4 | { 5 | private static App? _app; 6 | 7 | public static int Main(string[] args) 8 | { 9 | Microsoft.UI.Xaml.Application.Start(_ => _app = new App()); 10 | 11 | return 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/WasmCSS/Fonts.css: -------------------------------------------------------------------------------- 1 | /** 2 | When adding fonts here, make sure to add them using a base64 data uri, otherwise 3 | fonts loading are delayed, and text may get displayed incorrectly. 4 | */ 5 | 6 | /* https://github.com/unoplatform/uno/issues/3954 */ 7 | @font-face { 8 | font-family: 'Segoe UI'; 9 | src: local('Segoe UI'), local('-apple-system'), local('BlinkMacSystemFont'), local('Inter'), local('Cantarell'), local('Ubuntu'), local('Roboto'), local('Open Sans'), local('Noto Sans'), local('Helvetica Neue'), local('sans-serif'); 10 | } 11 | 12 | @font-face { 13 | font-family: 'Roboto'; 14 | src: url(./Uno.Fonts.Roboto/Fonts/Roboto-Light.ttf) format('truetype'); 15 | font-weight: 300; 16 | } 17 | 18 | @font-face { 19 | font-family: 'Roboto'; 20 | src: url(./Uno.Fonts.Roboto/Fonts/Roboto-Regular.ttf) format('truetype'); 21 | font-weight: 400; 22 | } 23 | 24 | @font-face { 25 | font-family: 'Roboto'; 26 | src: url(./Uno.Fonts.Roboto/Fonts/Roboto-Medium.ttf) format('truetype'); 27 | font-weight: 500; 28 | } 29 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/WasmScripts/AppManifest.js: -------------------------------------------------------------------------------- 1 | var UnoAppManifest = { 2 | displayName: "TodoApp.Uno" 3 | } 4 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/manifest.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "background_color": "#ffffff", 3 | "description": "TodoApp.Uno", 4 | "display": "standalone", 5 | "name": "TodoApp.Uno", 6 | "short_name": "TodoApp.Uno", 7 | "start_url": "/index.html", 8 | "theme_color": "#ffffff", 9 | "scope": "/" 10 | } 11 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/WebAssembly/wwwroot/staticwebapp.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationFallback": { 3 | "rewrite": "/index.html", 4 | "exclude": [ 5 | "*.{css,js}", 6 | "*.{png}", 7 | "*.{c,h,wasm,clr,pdb,dat,txt}" 8 | ] 9 | }, 10 | "routes": [ 11 | { 12 | "route": "/package_*", 13 | "headers": { 14 | "cache-control": "public, immutable, max-age=31536000" 15 | } 16 | }, 17 | { 18 | "route": "/*.ttf", 19 | "headers": { 20 | "cache-control": "public, immutable, max-age=31536000" 21 | } 22 | }, 23 | { 24 | "route": "/*", 25 | "headers": { 26 | "cache-control": "must-revalidate, max-age=3600" 27 | } 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Platforms/iOS/Main.iOS.cs: -------------------------------------------------------------------------------- 1 | using UIKit; 2 | 3 | namespace TodoApp.Uno.iOS; 4 | public class EntryPoint 5 | { 6 | // This is the main entry point of the application. 7 | public static void Main(string[] args) 8 | { 9 | // if you want to use a different Application Delegate class from "AppDelegate" 10 | // you can specify it here. 11 | UIApplication.Main(args, null, typeof(App)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/Shell.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace TodoApp.Uno.Presentation; 2 | 3 | public sealed partial class Shell : UserControl, IContentControlProvider 4 | { 5 | public Shell() 6 | { 7 | this.InitializeComponent(); 8 | } 9 | public ContentControl ContentControl => Splash; 10 | } 11 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Presentation/ShellViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace TodoApp.Uno.Presentation; 2 | 3 | public class ShellViewModel 4 | { 5 | private readonly INavigator _navigator; 6 | 7 | public ShellViewModel( 8 | INavigator navigator) 9 | { 10 | _navigator = navigator; 11 | // Add code here to initialize or attach event handlers to singleton services 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-arm64.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | FileSystem 8 | arm64 9 | win-arm64 10 | bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ 11 | true 12 | False 13 | False 14 | True 15 | False 16 | True 17 | 18 | 19 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-x64.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | FileSystem 8 | x64 9 | win-x64 10 | bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ 11 | true 12 | False 13 | False 14 | True 15 | False 16 | True 17 | 18 | 19 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/Properties/PublishProfiles/win-x86.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | FileSystem 8 | x86 9 | win-x86 10 | bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ 11 | true 12 | False 13 | False 14 | True 15 | False 16 | True 17 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/ReadMe.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | Welcome to the Uno Platform! 4 | 5 | To discover how to get started with your new app: https://aka.platform.uno/get-started 6 | 7 | For more information on how to use the Uno.Sdk or upgrade Uno Platform packages in your solution: https://aka.platform.uno/using-uno-sdk -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/ViewModels/NotificationEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace TodoApp.Uno.ViewModels; 6 | 7 | internal record NotificationEventArgs(string Title, string Message, bool IsError) 8 | { 9 | } 10 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/appsettings.development.json: -------------------------------------------------------------------------------- 1 | { 2 | "AppConfig": { 3 | "Environment": "Development" 4 | }, 5 | "ApiClient": { 6 | "Url": "https://localhost:5002", 7 | "UseNativeHandler": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/TodoApp.Uno/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AppConfig": { 3 | "Environment": "Production" 4 | }, 5 | "ApiClient": { 6 | "UseNativeHandler": true 7 | }, 8 | "LocalizationConfiguration": { 9 | "Cultures": [ 10 | "es", 11 | "fr", 12 | "pt-BR", 13 | "en" 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.Uno/global.json: -------------------------------------------------------------------------------- 1 | { 2 | // To update the version of Uno please update the version of the Uno.Sdk here. See https://aka.platform.uno/upgrade-uno-packages for more information. 3 | "msbuild-sdks": { 4 | "Uno.Sdk": "5.4.5" 5 | }, 6 | "sdk":{ 7 | "allowPrerelease": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WPF/App.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WPF/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Windows; 6 | 7 | [assembly: ThemeInfo( 8 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 9 | //(used if a resource is not found in the page, 10 | // or application resource dictionaries) 11 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 12 | //(used if a resource is not found in the page, 13 | // app, or any theme specific resource dictionaries) 14 | )] 15 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WPF/Converters/BooleanToImageConverter.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Globalization; 6 | using System.Windows.Data; 7 | using System.Windows.Media.Imaging; 8 | 9 | namespace TodoApp.WPF.Converters; 10 | 11 | /// 12 | /// A converter to convert the boolean for IsComplete into one of two images. 13 | /// 14 | public class BooleanToImageConverter : IValueConverter 15 | { 16 | private const string baseUri = "pack://application:,,,/Images"; 17 | 18 | public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | if (value is bool booleanValue) 21 | { 22 | return new BitmapImage(new Uri(booleanValue ? $"{baseUri}/completed.png" : $"{baseUri}/incomplete.png")); 23 | } 24 | 25 | return null; 26 | } 27 | 28 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 29 | { 30 | throw new NotImplementedException(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WPF/Database/IDbInitializer.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace TodoApp.WPF.Database; 6 | 7 | /// 8 | /// An interface to initialize a database. 9 | /// 10 | public interface IDbInitializer 11 | { 12 | /// 13 | /// Synchronously initialize the database. 14 | /// 15 | void Initialize(); 16 | 17 | /// 18 | /// Asynchronously initialize the database. 19 | /// 20 | /// A to observe. 21 | /// A task that resolves when complete. 22 | Task InitializeAsync(CancellationToken cancellationToken = default); 23 | } 24 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WPF/Database/OfflineClientEntity.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.ComponentModel.DataAnnotations; 6 | 7 | namespace TodoApp.WPF.Database; 8 | 9 | /// 10 | /// An abstract class for working with offline entities. 11 | /// 12 | public abstract class OfflineClientEntity 13 | { 14 | [Key] 15 | public string Id { get; set; } = Guid.NewGuid().ToString("N"); 16 | public DateTimeOffset? UpdatedAt { get; set; } 17 | public string? Version { get; set; } 18 | public bool Deleted { get; set; } 19 | } 20 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WPF/Database/TodoItem.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace TodoApp.WPF.Database; 6 | public class TodoItem : OfflineClientEntity 7 | { 8 | public string Title { get; set; } = string.Empty; 9 | public bool IsComplete { get; set; } = false; 10 | } 11 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WPF/Images/completed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.WPF/Images/completed.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WPF/Images/incomplete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.WPF/Images/incomplete.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WPF/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | using System.Windows.Input; 8 | using TodoApp.WPF.Database; 9 | using TodoApp.WPF.ViewModels; 10 | 11 | namespace TodoApp.WPF; 12 | 13 | /// 14 | /// Interaction logic for MainWindow.xaml 15 | /// 16 | public partial class MainWindow : Window 17 | { 18 | private readonly TodoListViewModel viewModel; 19 | 20 | public MainWindow() 21 | { 22 | InitializeComponent(); 23 | this.viewModel = App.GetRequiredService(); 24 | DataContext = this.viewModel; 25 | } 26 | 27 | protected void ListViewItem_DoubleClickEventHandler(object sender, MouseButtonEventArgs e) 28 | { 29 | TodoItem? item = ((ListViewItem)sender).Content as TodoItem; 30 | this.viewModel.UpdateItemCommand.Execute(item); 31 | } 32 | } -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WPF/TodoApp.WPF.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WinExe 5 | net9.0-windows 6 | enable 7 | enable 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/App.xaml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/Assets/AddItem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.WinUI3/Assets/AddItem.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.WinUI3/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/Assets/RefreshItems.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.WinUI3/Assets/RefreshItems.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.WinUI3/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.WinUI3/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.WinUI3/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.WinUI3/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.WinUI3/Assets/StoreLogo.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/samples/todoapp/TodoApp.WinUI3/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/Database/IDbInitializer.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace TodoApp.WinUI3.Database; 9 | 10 | /// 11 | /// An interface to initialize a database. 12 | /// 13 | public interface IDbInitializer 14 | { 15 | /// 16 | /// Synchronously initialize the database. 17 | /// 18 | void Initialize(); 19 | 20 | /// 21 | /// Asynchronously initialize the database. 22 | /// 23 | /// A to observe. 24 | /// A task that resolves when complete. 25 | Task InitializeAsync(CancellationToken cancellationToken = default); 26 | } 27 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/Database/OfflineClientEntity.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | namespace TodoApp.WinUI3.Database; 9 | 10 | /// 11 | /// An abstract class for working with offline entities. 12 | /// 13 | public abstract class OfflineClientEntity 14 | { 15 | [Key] 16 | public string Id { get; set; } 17 | public DateTimeOffset? UpdatedAt { get; set; } 18 | public string Version { get; set; } 19 | public bool Deleted { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/Database/TodoItem.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Text.Json; 6 | 7 | namespace TodoApp.WinUI3.Database; 8 | 9 | public class TodoItem : OfflineClientEntity 10 | { 11 | public string Title { get; set; } = string.Empty; 12 | public bool IsComplete { get; set; } = false; 13 | 14 | public override string ToString() 15 | => JsonSerializer.Serialize(this); 16 | } -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "TodoApp.WinUI3 (Package)": { 4 | "commandName": "MsixPackage" 5 | }, 6 | "TodoApp.WinUI3 (Unpackaged)": { 7 | "commandName": "Project" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/ViewModels/NotificationEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace TodoApp.WinUI3.ViewModels; 6 | 7 | internal record NotificationEventArgs(string Title, string Message, bool IsError) 8 | { 9 | } 10 | -------------------------------------------------------------------------------- /samples/todoapp/TodoApp.WinUI3/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | PerMonitorV2 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/CommunityToolkit.Datasync.Client.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | The client capabilities for developing applications using the Datasync Toolkit. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/Exceptions/DatasyncHttpException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Client; 6 | 7 | /// 8 | /// Creates a new . 9 | /// 10 | public class DatasyncHttpException(ServiceResponse serviceResponse) : DatasyncException(serviceResponse.ReasonPhrase) 11 | { 12 | /// 13 | /// The service response that is generating the exception. 14 | /// 15 | public ServiceResponse ServiceResponse { get; } = serviceResponse; 16 | } 17 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/Exceptions/DatasyncPullException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics.CodeAnalysis; 6 | 7 | namespace CommunityToolkit.Datasync.Client.Exceptions; 8 | 9 | /// 10 | /// An internal exception generated during the pull operation. 11 | /// 12 | internal class DatasyncPullException : DatasyncException 13 | { 14 | /// 15 | [ExcludeFromCodeCoverage] 16 | public DatasyncPullException() 17 | { 18 | } 19 | 20 | /// 21 | [ExcludeFromCodeCoverage] 22 | public DatasyncPullException(string? message) : base(message) 23 | { 24 | } 25 | 26 | /// 27 | [ExcludeFromCodeCoverage] 28 | public DatasyncPullException(string? message, Exception? innerException) : base(message, innerException) 29 | { 30 | } 31 | 32 | /// 33 | /// The service response for the error. 34 | /// 35 | public required ServiceResponse ServiceResponse { get; init; } 36 | } 37 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/Http/BasicHttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Client.Http; 6 | 7 | /// 8 | /// A implementation that always 9 | /// returns the same . 10 | /// 11 | /// The to use 12 | internal class BasicHttpClientFactory(HttpClient client) : IHttpClientFactory 13 | { 14 | /// 15 | public HttpClient CreateClient(string name) => client; 16 | } 17 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/Offline/DeltaTokenStore/DatasyncDeltaToken.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.ComponentModel.DataAnnotations; 6 | 7 | namespace CommunityToolkit.Datasync.Client.Offline; 8 | 9 | /// 10 | /// A mapping for the delta-token store, which records the last sequence number of 11 | /// the entity that was synchronized (normally a time stamp). 12 | /// 13 | public class DatasyncDeltaToken 14 | { 15 | /// 16 | /// The ID of the entity type. 17 | /// 18 | [Key] 19 | public required string Id { get; set; } 20 | 21 | /// 22 | /// The value of the sequence number. 23 | /// 24 | public required long Value { get; set; } 25 | } 26 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/Offline/DoNotSynchronizeAttribute.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Client.Offline; 6 | 7 | /// 8 | /// An attribute for signifying that the DbSet should not be synchronized with 9 | /// a remote datasync service. 10 | /// 11 | [AttributeUsage(AttributeTargets.Property)] 12 | public class DoNotSynchronizeAttribute : Attribute 13 | { 14 | /// 15 | /// Creates a new instance. 16 | /// 17 | public DoNotSynchronizeAttribute() 18 | { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/Offline/Models/PullOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.ComponentModel.DataAnnotations; 6 | 7 | namespace CommunityToolkit.Datasync.Client.Offline; 8 | 9 | /// 10 | /// The options to use for pushing operations to the service. 11 | /// 12 | public class PullOptions 13 | { 14 | /// 15 | /// The number of parallel operations to use for the push operation. 16 | /// 17 | [Required, Range(1, 8, ErrorMessage = "Invalid number of parallel operations.")] 18 | public int ParallelOperations { get; set; } = 1; 19 | 20 | /// 21 | /// If true, SaveChangesAsync() is called after every service request is received. 22 | /// 23 | public bool SaveAfterEveryServiceRequest { get; set; } = true; 24 | } 25 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/Offline/Operations/IPullOperationManager.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Client.Offline.Models; 6 | 7 | namespace CommunityToolkit.Datasync.Client.Offline.Operations; 8 | 9 | /// 10 | /// The interface describing how to pull elements from the remote service 11 | /// 12 | internal interface IPullOperationManager 13 | { 14 | /// 15 | /// Executes a set of pull requests. 16 | /// 17 | /// The list of pull requests to execute.. 18 | /// The pull options to use. 19 | /// A to observe. 20 | /// The results of the pull operation. 21 | Task ExecuteAsync(IEnumerable pullRequests, PullOptions pullOptions, CancellationToken cancellationToken); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/Offline/OperationsQueue/IOperationsQueueManager.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Client.Offline.OperationsQueue; 6 | 7 | /// 8 | /// The definition of the required parts of the operations queue manager used 9 | /// by the pull operation. 10 | /// 11 | internal interface IOperationsQueueManager 12 | { 13 | /// 14 | /// Counts the number of operations enqueued in the operations queue for the given 15 | /// entity type. 16 | /// 17 | /// The entity type being processed. 18 | /// A to observe. 19 | /// The number of operations in queue for the entity. 20 | Task CountOperationsInQueueAsync(Type entityType, CancellationToken cancellationToken = default); 21 | } 22 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/Offline/OperationsQueue/PushOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.ComponentModel.DataAnnotations; 6 | 7 | namespace CommunityToolkit.Datasync.Client.Offline; 8 | 9 | /// 10 | /// The options to use for pushing operations to the service. 11 | /// 12 | public class PushOptions 13 | { 14 | /// 15 | /// The number of parallel operations to use for the push operation. 16 | /// 17 | [Required, Range(1, 8, ErrorMessage = "Invalid number of parallel operations.")] 18 | public int ParallelOperations { get; set; } = 1; 19 | } 20 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/Paging/FuncAsyncPageable.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Client.Paging; 6 | 7 | /// 8 | /// An implementation of the class that reads 9 | /// each page in a query from a paging function that is supplied on construction. 10 | /// 11 | internal class FuncAsyncPageable(Func>> pageFunc) : AsyncPageable() 12 | { 13 | /// 14 | public override async IAsyncEnumerable> AsPages(string? continuationToken = null) 15 | { 16 | do 17 | { 18 | Page pageResponse = await pageFunc(continuationToken).ConfigureAwait(false); 19 | continuationToken = pageResponse.NextLink?.ToString(); 20 | yield return pageResponse; 21 | } while (continuationToken != null); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/Paging/Page.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Client; 6 | 7 | /// 8 | /// A response to a GetPageAsync request. 9 | /// 10 | /// The entity stored in the Items list. 11 | public class Page 12 | { 13 | /// 14 | /// The items in a page. 15 | /// 16 | public IEnumerable Items { get; set; } = []; 17 | 18 | /// 19 | /// The number of items that would be returned by the query, 20 | /// if not for paging. 21 | /// 22 | public long? Count { get; set; } 23 | 24 | /// 25 | /// The Uri to the next page in the result set. 26 | /// 27 | public string? NextLink { get; set; } 28 | } 29 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/Serialization/EntityMetadata.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Client.Serialization; 6 | 7 | /// 8 | /// A representation of just the metadata for an entity. 9 | /// 10 | internal class EntityMetadata 11 | { 12 | /// 13 | /// The globally unique ID of the entity. 14 | /// 15 | public string? Id { get; set; } 16 | 17 | /// 18 | /// The date/time stamp for the last updated state. 19 | /// 20 | public DateTimeOffset? UpdatedAt { get; set; } 21 | 22 | /// 23 | /// The version of the entity. 24 | /// 25 | public string? Version { get; set; } 26 | 27 | /// 28 | /// True if the entity is deleted; false otherwise. 29 | /// 30 | public bool Deleted { get; set; } 31 | } 32 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Client/Threading/DisposeAction.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Client.Threading; 6 | 7 | /// 8 | /// An that runs an action on disposing. 9 | /// 10 | /// 11 | /// This is most often used to release an asynchronous lock when disposed. 12 | /// 13 | internal struct DisposeAction(Action action) : IDisposable 14 | { 15 | bool isDisposed = false; 16 | 17 | public void Dispose() 18 | { 19 | if (this.isDisposed) 20 | { 21 | return; 22 | } 23 | 24 | this.isDisposed = true; 25 | action(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.Abstractions/CommunityToolkit.Datasync.Server.Abstractions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Abstractions for developing server-side applications using the Datasync Toolkit. 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.Abstractions/Exceptions/DatasyncToolkitException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics.CodeAnalysis; 6 | 7 | namespace CommunityToolkit.Datasync.Server; 8 | 9 | /// 10 | /// The base exception class for all exceptions thrown by the Datasync Toolkit. 11 | /// 12 | [ExcludeFromCodeCoverage] 13 | public class DatasyncToolkitException : Exception 14 | { 15 | /// 16 | public DatasyncToolkitException() : base() 17 | { 18 | } 19 | 20 | /// 21 | public DatasyncToolkitException(string? message) : base(message) 22 | { 23 | } 24 | 25 | /// 26 | public DatasyncToolkitException(string? message, Exception? innerException) : base(message, innerException) 27 | { 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.Abstractions/Exceptions/RepositoryException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics.CodeAnalysis; 6 | 7 | namespace CommunityToolkit.Datasync.Server; 8 | 9 | /// 10 | /// An exception to indicate that an error occurred in the repository implementation. 11 | /// 12 | [ExcludeFromCodeCoverage] 13 | public class RepositoryException : DatasyncToolkitException 14 | { 15 | /// 16 | public RepositoryException() : base() 17 | { 18 | } 19 | 20 | /// 21 | public RepositoryException(string? message) : base(message) 22 | { 23 | } 24 | 25 | /// 26 | public RepositoryException(string? message, Exception? innerException) : base(message, innerException) 27 | { 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.Abstractions/Json/TimeOnlyConverter.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Globalization; 6 | using System.Text.Json; 7 | using System.Text.Json.Serialization; 8 | 9 | namespace CommunityToolkit.Datasync.Server.Abstractions.Json; 10 | 11 | /// 12 | /// A specialized converter for the type that 13 | /// handles the specific requirements of the Datasync Toolkit. 14 | /// 15 | public class TimeOnlyConverter : JsonConverter 16 | { 17 | private const string format = "HH:mm:ss.fff"; 18 | 19 | /// 20 | public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 21 | => TimeOnly.Parse(reader.GetString() ?? string.Empty); 22 | 23 | /// 24 | public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options) 25 | => writer.WriteStringValue(value.ToString(format, CultureInfo.InvariantCulture)); 26 | } 27 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.Abstractions/Tables/TableOperation.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Server; 6 | 7 | /// 8 | /// A list of valid operation types for a single operation on a table. 9 | /// 10 | /// 11 | /// This is used in an to pass the 12 | /// operation type being requested by the client. 13 | /// 14 | public enum TableOperation 15 | { 16 | /// 17 | /// An entity is being created. 18 | /// 19 | Create, 20 | 21 | /// 22 | /// An entity is being deleted. 23 | /// 24 | Delete, 25 | 26 | /// 27 | /// The data store is being queried. 28 | /// 29 | Query, 30 | 31 | /// 32 | /// An entity is being read. 33 | /// 34 | Read, 35 | 36 | /// 37 | /// An entity is being updated. 38 | /// 39 | Update 40 | } 41 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.Automapper/CommunityToolkit.Datasync.Server.Automapper.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | A repository for the server-side of the Datasync Toolkit that uses Automapper. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.CosmosDb/CommunityToolkit.Datasync.Server.CosmosDb.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | enable 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.CosmosDb/CosmosTableDataOfT.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Server.CosmosDb; 6 | /// 7 | /// Base implementation of for entities that are stored in a shared CosmosDB collection. 8 | /// 9 | /// The type of the Table Data 10 | public abstract class CosmosTableData : CosmosTableData where T : CosmosTableData 11 | { 12 | /// 13 | /// The entity type for the data. Used as the default partition key for shared containers. 14 | /// 15 | public virtual string Entity => typeof(T).Name; 16 | } 17 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.EntityFrameworkCore/BaseEntityTableData.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.ComponentModel.DataAnnotations; 6 | 7 | namespace CommunityToolkit.Datasync.Server.EntityFrameworkCore; 8 | 9 | /// 10 | /// The base class for all the Entity Framework Core based table data classes. 11 | /// 12 | public abstract class BaseEntityTableData : ITableData 13 | { 14 | /// 15 | [Key] 16 | public virtual string Id { get; set; } = string.Empty; 17 | 18 | /// 19 | public virtual bool Deleted { get; set; } = false; 20 | 21 | /// 22 | public virtual DateTimeOffset? UpdatedAt { get; set; } = DateTimeOffset.UnixEpoch; 23 | 24 | /// 25 | public virtual byte[] Version { get; set; } = Array.Empty(); 26 | 27 | /// 28 | public bool Equals(ITableData? other) 29 | => other != null && Id == other.Id && Version.SequenceEqual(other.Version); 30 | } 31 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.EntityFrameworkCore/CommunityToolkit.Datasync.Server.EntityFrameworkCore.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | An Entity Framework Core based repository for use with the Datasync Toolkit. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.EntityFrameworkCore/EntityTableData.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.EntityFrameworkCore; 6 | using System.ComponentModel.DataAnnotations; 7 | using System.ComponentModel.DataAnnotations.Schema; 8 | 9 | namespace CommunityToolkit.Datasync.Server.EntityFrameworkCore; 10 | 11 | /// 12 | /// A version of the that is compatible with 13 | /// most of the Entity Framework Core drivers. 14 | /// 15 | [Index(nameof(UpdatedAt), nameof(Deleted))] 16 | public class EntityTableData : BaseEntityTableData 17 | { 18 | /// 19 | [DatabaseGenerated(DatabaseGeneratedOption.Computed)] 20 | public override DateTimeOffset? UpdatedAt { get; set; } = DateTimeOffset.UnixEpoch; 21 | 22 | /// 23 | [Timestamp] 24 | public override byte[] Version { get; set; } = []; 25 | } 26 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.EntityFrameworkCore/RepositoryControlledEntityTableData.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Server.EntityFrameworkCore; 6 | 7 | /// 8 | /// A version of the that updates both the 9 | /// UpdatedAt and Version fields within the repository (instead 10 | /// of relying on the database server to do it). 11 | /// 12 | public class RepositoryControlledEntityTableData : BaseEntityTableData 13 | { 14 | /// 15 | [UpdatedByRepository] 16 | public override DateTimeOffset? UpdatedAt { get; set; } = DateTimeOffset.UnixEpoch; 17 | 18 | /// 19 | [UpdatedByRepository] 20 | public override byte[] Version { get; set; } = []; 21 | } 22 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.EntityFrameworkCore/SqliteEntityTableData.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Server.EntityFrameworkCore; 6 | 7 | /// 8 | /// A version of the that does automatic timestamping. 9 | /// 10 | public class SqliteEntityTableData : BaseEntityTableData 11 | { 12 | } 13 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.EntityFrameworkCore/UpdatedByRepositoryAttribute.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Server.EntityFrameworkCore; 6 | 7 | /// 8 | /// The is used to signify that 9 | /// the property should be updated by the repository (and not by the database 10 | /// server). It is only valid on UpdatedAt and Version attributes. 11 | /// 12 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] 13 | public class UpdatedByRepositoryAttribute : Attribute 14 | { 15 | } 16 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.InMemory/CommunityToolkit.Datasync.Server.InMemory.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | An in-memory repository for the server-side of the Datasync Toolkit. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.InMemory/InMemoryTableData.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Server.InMemory; 6 | 7 | /// 8 | /// The base class for the entities stored in an in-memory repository. 9 | /// 10 | public class InMemoryTableData : ITableData 11 | { 12 | /// 13 | public string Id { get; set; } = string.Empty; 14 | 15 | /// 16 | public bool Deleted { get; set; } = false; 17 | 18 | /// 19 | public DateTimeOffset? UpdatedAt { get; set; } = DateTimeOffset.UnixEpoch; 20 | 21 | /// 22 | public byte[] Version { get; set; } = Array.Empty(); 23 | 24 | /// 25 | public bool Equals(ITableData? other) 26 | => other != null && Id == other.Id && Version.SequenceEqual(other.Version); 27 | } 28 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.LiteDb/CommunityToolkit.Datasync.Server.LiteDb.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | A repository for the server-side of the Datasync Toolkit that uses LiteDb for storage. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.LiteDb/LiteDbTableData.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using LiteDB; 6 | 7 | namespace CommunityToolkit.Datasync.Server.LiteDb; 8 | 9 | /// 10 | /// An implementation of the interface for 11 | /// handling entities in a LiteDB database. 12 | /// 13 | public class LiteDbTableData : ITableData 14 | { 15 | /// 16 | [BsonId] 17 | public string Id { get; set; } = string.Empty; 18 | 19 | /// 20 | public bool Deleted { get; set; } = false; 21 | 22 | /// 23 | public DateTimeOffset? UpdatedAt { get; set; } = DateTimeOffset.UnixEpoch; 24 | 25 | /// 26 | public byte[] Version { get; set; } = []; 27 | 28 | /// 29 | public bool Equals(ITableData? other) 30 | => other != null && Id == other.Id && Version.SequenceEqual(other.Version); 31 | } 32 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.MongoDB/CommunityToolkit.Datasync.Server.MongoDB.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | A repository for the server-side of the Datasync Toolkit that uses MongoDB for storage. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.MongoDB/MongoTableData.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using MongoDB.Bson.Serialization.Attributes; 6 | 7 | namespace CommunityToolkit.Datasync.Server.MongoDB; 8 | 9 | /// 10 | /// An implementation of the interface for 11 | /// handling entities in a MongoDB database. 12 | /// 13 | public class MongoTableData : ITableData 14 | { 15 | /// 16 | [BsonId] 17 | public string Id { get; set; } = string.Empty; 18 | 19 | /// 20 | public bool Deleted { get; set; } = false; 21 | 22 | /// 23 | public DateTimeOffset? UpdatedAt { get; set; } = DateTimeOffset.UnixEpoch; 24 | 25 | /// 26 | public byte[] Version { get; set; } = []; 27 | 28 | /// 29 | public bool Equals(ITableData? other) 30 | => other != null && Id == other.Id && Version.SequenceEqual(other.Version); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.NSwag/CommunityToolkit.Datasync.Server.NSwag.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Provides necessary capabilities for supporting the Datasync server library when using NSwag for creating OpenAPI definitions. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.OpenApi/CommunityToolkit.Datasync.Server.OpenApi.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Provides necessary capabilities for supporting the Datasync server library when using the official OpenApi generator. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.OpenApi/OpenApiExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.AspNetCore.OpenApi; 6 | 7 | namespace CommunityToolkit.Datasync.Server.OpenApi; 8 | 9 | /// 10 | /// A set of extension methods to make it easier to configure the OpenAPI options for the Datasync services. 11 | /// 12 | public static class OpenApiExtensions 13 | { 14 | /// 15 | /// Adds the appropriate transformers to the OpenAPI options to support the Datasync services. 16 | /// 17 | /// The to modify. 18 | /// The modified for chaining. 19 | public static OpenApiOptions AddDatasyncTransformers(this OpenApiOptions options) 20 | { 21 | _ = options 22 | .AddOperationTransformer(); 23 | 24 | return options; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.Swashbuckle/CommunityToolkit.Datasync.Server.Swashbuckle.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Provides necessary capabilities for supporting the Datasync server library when using Swashbuckle for creating OpenAPI definitions. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server.Swashbuckle/SwaggerGenExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Swashbuckle.AspNetCore.SwaggerGen; 7 | using System.Reflection; 8 | 9 | namespace CommunityToolkit.Datasync.Server.Swashbuckle; 10 | 11 | /// 12 | /// Extensions to enable the developer to wire in the Datasync Controllers into 13 | /// a Swashbuckle SwaggerGen() pipeline. 14 | /// 15 | public static class SwaggerGenExtensions 16 | { 17 | /// 18 | /// Adds the Datasync to the SwaggerGen pipeline. 19 | /// 20 | /// The representing the Swashbuckle configuration pipeline. 21 | public static void AddDatasyncControllers(this SwaggerGenOptions options) 22 | { 23 | options.DocumentFilter(Assembly.GetCallingAssembly()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server/CommunityToolkit.Datasync.Server.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | A server-side component for implementing a datsync controller. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server/Models/IDatasyncServiceOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Text.Json; 6 | 7 | namespace CommunityToolkit.Datasync.Server; 8 | 9 | /// 10 | /// The definition of the service options available when configuring a Datasync controller. 11 | /// 12 | /// 13 | /// This is used in dependency injection to configure the various attributes with standardized options. 14 | /// 15 | public interface IDatasyncServiceOptions 16 | { 17 | /// 18 | /// The serializer options to use for communication with a Datasync client. 19 | /// 20 | JsonSerializerOptions JsonSerializerOptions { get; } 21 | } 22 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Datasync.Server/Models/ModelCache.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.OData.Edm; 6 | using Microsoft.OData.ModelBuilder; 7 | using System.Collections.Concurrent; 8 | 9 | namespace CommunityToolkit.Datasync.Server.Private; 10 | 11 | /// 12 | /// Model cache for the needed for each table controller. 13 | /// 14 | internal static class ModelCache 15 | { 16 | private static readonly ConcurrentDictionary _cache = new(); 17 | 18 | internal static IEdmModel GetEdmModel(Type type) 19 | { 20 | if (!_cache.TryGetValue(type, out IEdmModel? model)) 21 | { 22 | ODataConventionModelBuilder modelBuilder = new(); 23 | _ = modelBuilder.EnableLowerCamelCase().AddEntityType(type); 24 | model = modelBuilder.GetEdmModel(); 25 | _ = _cache.TryAdd(type, model); 26 | } 27 | 28 | return model; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /templates/Template.DatasyncServer/.template.config/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/template", 3 | "author": "Community Toolkit", 4 | "classifications": [ "Cloud", "Web", "Mobile", "WebAPI" ], 5 | "identity": "CommunityToolkit.Datasync.Server.Template.CSharp", 6 | "name": "ASP.NET Core Datasync Server", 7 | "shortName": "datasync-server", 8 | "sourceName": "Template.DatasyncServer", 9 | "preferNameDirectory": true, 10 | "tags": { 11 | "language": "C#", 12 | "type": "project" 13 | }, 14 | "symbols": { 15 | "secretsGuid": { 16 | "type": "generated", 17 | "generator": "guid", 18 | "replaces": "{SECRETS-GUID}", 19 | "parameters": { 20 | "defaultFormat": "D" 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /templates/Template.DatasyncServer/Controllers/TodoItemController.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Datasync.Server; 2 | using CommunityToolkit.Datasync.Server.EntityFrameworkCore; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Template.DatasyncServer.Db; 5 | 6 | namespace Template.DatasyncServer.Controllers 7 | { 8 | [Route("tables/todoitem")] 9 | public class TodoItemController : TableController 10 | { 11 | public TodoItemController(AppDbContext context) 12 | : base(new EntityTableRepository(context)) 13 | { 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /templates/Template.DatasyncServer/Models/AppDbContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | 3 | namespace Template.DatasyncServer.Db 4 | { 5 | public class AppDbContext : DbContext 6 | { 7 | public AppDbContext(DbContextOptions options) : base(options) 8 | { 9 | } 10 | 11 | /// 12 | /// The dataset for the TodoItems. 13 | /// 14 | public DbSet TodoItems => Set(); 15 | 16 | /// 17 | /// Do any database initialization required. 18 | /// 19 | /// A task that completes when the database is initialized 20 | public async Task InitializeDatabaseAsync() 21 | { 22 | await this.Database.EnsureCreatedAsync().ConfigureAwait(false); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /templates/Template.DatasyncServer/Models/TodoItem.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Datasync.Server.EntityFrameworkCore; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Template.DatasyncServer.Db 5 | { 6 | /// 7 | /// The fields in this class must match the fields in Models/TodoItem.cs 8 | /// for the TodoApp.Data project. 9 | /// 10 | public class TodoItem : EntityTableData 11 | { 12 | [Required, MinLength(1)] 13 | public string Title { get; set; } = ""; 14 | 15 | public bool IsComplete { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /templates/Template.DatasyncServer/Program.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Datasync.Server; 2 | using Microsoft.EntityFrameworkCore; 3 | using Template.DatasyncServer.Db; 4 | 5 | var builder = WebApplication.CreateBuilder(args); 6 | var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); 7 | 8 | builder.Services.AddDbContext(options => options.UseSqlServer(connectionString)); 9 | builder.Services.AddDatasyncControllers(); 10 | 11 | var app = builder.Build(); 12 | 13 | // Initialize the database 14 | using (var scope = app.Services.CreateScope()) 15 | { 16 | var context = scope.ServiceProvider.GetRequiredService(); 17 | await context.InitializeDatabaseAsync().ConfigureAwait(false); 18 | } 19 | 20 | // Configure and run the web service. 21 | app.MapControllers(); 22 | app.Run(); -------------------------------------------------------------------------------- /templates/Template.DatasyncServer/Properties/serviceDependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "mssql1": { 4 | "type": "mssql", 5 | "connectionId": "AppDbContext" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /templates/Template.DatasyncServer/Template.DatasyncServer.csproj.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | net9.0 4 | enable 5 | enable 6 | latest 7 | {SECRETS-GUID} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | all 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | 18 | 19 | -------------------------------------------------------------------------------- /templates/Template.DatasyncServer/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "CommunityToolkit.Datasync": "Information", 5 | "Default": "Information", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /templates/Template.DatasyncServer/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoItemsSample;Trusted_Connection=True;MultipleActiveResultSets=true" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Information", 8 | "Microsoft": "Warning", 9 | "Microsoft.Hosting.Lifetime": "Information" 10 | } 11 | }, 12 | "AllowedHosts": "*" 13 | } -------------------------------------------------------------------------------- /tests/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | 3 | # 4 | # Settings below here are required to silence the code style warnings that conflict with XUnit. 5 | # 6 | 7 | # IDE0058: Expression value is never used 8 | csharp_style_unused_value_expression_statement_preference = discard_variable 9 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Client.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | global using FluentAssertions; 6 | global using System.Diagnostics.CodeAnalysis; 7 | global using Xunit; 8 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Client.Test/Helpers/ClientTestData.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | #pragma warning disable IDE0028 // Simplify collection initialization 6 | 7 | namespace CommunityToolkit.Datasync.Client.Test.Helpers; 8 | 9 | /// 10 | /// A set of generators for the entity data. 11 | /// 12 | [ExcludeFromCodeCoverage] 13 | public class ClientTestData 14 | { 15 | /// 16 | /// A set of invalid IDs for testing 17 | /// 18 | public static TheoryData InvalidIds 19 | { 20 | get 21 | { 22 | TheoryData data = new(); 23 | data.Add(""); 24 | data.Add(" "); 25 | data.Add("\t"); 26 | data.Add("abcde fgh"); 27 | data.Add("!!!"); 28 | data.Add("?"); 29 | data.Add(";"); 30 | data.Add("{EA235ADF-9F38-44EA-8DA4-EF3D24755767}"); 31 | data.Add("###"); 32 | return data; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Client.Test/Helpers/Disposable.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Client.Test.Helpers; 6 | 7 | [ExcludeFromCodeCoverage] 8 | public abstract class Disposable : IDisposable 9 | { 10 | protected virtual void Dispose(bool disposing) 11 | { 12 | if (disposing) 13 | { 14 | // TODO: dispose managed state (managed objects) 15 | } 16 | } 17 | 18 | public void Dispose() 19 | { 20 | Dispose(disposing: true); 21 | GC.SuppressFinalize(this); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Client.Test/Http/Platform_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Client.Http; 6 | 7 | namespace CommunityToolkit.Datasync.Client.Test.Http; 8 | 9 | [ExcludeFromCodeCoverage] 10 | public class Platform_Tests 11 | { 12 | [Fact] 13 | public void AssemblyVersion_IsNotEmpty() 14 | { 15 | Platform.AssemblyVersion.Should().NotBeEmpty(); 16 | } 17 | 18 | [Fact] 19 | public void UserAgentDetails_IsNotEmpty() 20 | { 21 | Platform.UserAgentDetails.Should().NotBeEmpty(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Client.Test/Query/Linq/ImplicitConversion_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Client.Query.Linq; 6 | using CommunityToolkit.Datasync.TestCommon.Models; 7 | 8 | namespace CommunityToolkit.Datasync.Client.Test.Query.Linq; 9 | 10 | [ExcludeFromCodeCoverage] 11 | public class ImplicitConversion_Tests 12 | { 13 | [Theory] 14 | [InlineData(typeof(float), typeof(int), false)] 15 | [InlineData(typeof(KitchenSinkState), typeof(int), true)] 16 | [InlineData(typeof(DateTime), typeof(DateTimeOffset), false)] 17 | [InlineData(typeof(int), typeof(int), true)] 18 | public void ImplicitConversions_Works(Type from, Type to, bool expected) 19 | { 20 | ImplicitConversions.IsImplicitConversion(from, to).Should().Be(expected); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Client.Test/Threading/DisposableLock_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Client.Threading; 6 | 7 | namespace CommunityToolkit.Datasync.Client.Test.Threading; 8 | 9 | [ExcludeFromCodeCoverage] 10 | public class DisposableLock_Tests 11 | { 12 | [Fact] 13 | public void AcquireLock_Works() 14 | { 15 | DisposableLock sut = new(); 16 | 17 | sut.IsLocked().Should().BeFalse(); 18 | using (sut.AcquireLock()) 19 | { 20 | sut.IsLocked().Should().BeTrue(); 21 | } 22 | 23 | sut.IsLocked().Should().BeFalse(); 24 | } 25 | 26 | [Fact] 27 | public async Task AcquireLockAsync_Works() 28 | { 29 | DisposableLock sut = new(); 30 | 31 | sut.IsLocked().Should().BeFalse(); 32 | using (await sut.AcquireLockAsync()) 33 | { 34 | sut.IsLocked().Should().BeTrue(); 35 | } 36 | 37 | sut.IsLocked().Should().BeFalse(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Client.Test/Threading/DisposeAction_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Client.Threading; 6 | 7 | namespace CommunityToolkit.Datasync.Client.Test.Threading; 8 | 9 | [ExcludeFromCodeCoverage] 10 | public class DisposeAction_Tests 11 | { 12 | [Fact] 13 | public void DisposeAction_CallsAction_OnDispose() 14 | { 15 | bool isCalled = false; 16 | using (DisposeAction sut = new(() => isCalled = true)) 17 | { 18 | Assert.False(isCalled); 19 | } 20 | 21 | Assert.True(isCalled); 22 | } 23 | 24 | [Fact] 25 | public void DisposeAction_CanDisposeTwice() 26 | { 27 | int isCalled = 0; 28 | using (DisposeAction sut = new(() => isCalled++)) 29 | { 30 | Assert.Equal(0, isCalled); 31 | sut.Dispose(); 32 | Assert.Equal(1, isCalled); 33 | } 34 | 35 | Assert.Equal(1, isCalled); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.Abstractions.Test/CommunityToolkit.Datasync.Server.Abstractions.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | runtime; build; native; contentfiles; analyzers; buildtransitive 8 | all 9 | 10 | 11 | runtime; build; native; contentfiles; analyzers; buildtransitive 12 | all 13 | 14 | 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | all 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.Abstractions.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | global using FluentAssertions; 6 | global using System.Diagnostics.CodeAnalysis; 7 | global using Xunit; 8 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.Automapper.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | global using FluentAssertions; 6 | global using System.Diagnostics.CodeAnalysis; 7 | global using Xunit; -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.Automapper.Test/Helpers/MapperProfile.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using AutoMapper; 6 | using CommunityToolkit.Datasync.TestCommon.Databases; 7 | 8 | namespace CommunityToolkit.Datasync.Server.Automapper.Test.Helpers; 9 | 10 | [ExcludeFromCodeCoverage] 11 | public class MapperProfile : Profile 12 | { 13 | public MapperProfile() 14 | { 15 | CreateMap().ReverseMap(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.CosmosDb.Test/CommunityToolkit.Datasync.Server.CosmosDb.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | enable 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.CosmosDb.Test/Models/CosmosDbMovie.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.TestCommon.Models; 6 | 7 | namespace CommunityToolkit.Datasync.Server.CosmosDb.Test.Models; 8 | public class CosmosDbMovie : CosmosTableData, IMovie 9 | { 10 | public bool BestPictureWinner { get; set; } 11 | 12 | public int Duration { get; set; } 13 | 14 | public MovieRating Rating { get; set; } 15 | 16 | public DateOnly ReleaseDate { get; set; } 17 | 18 | public string Title { get; set; } 19 | 20 | public int Year { get; set; } 21 | } 22 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.EntityFrameworkCore.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | global using FluentAssertions; 6 | global using System.Diagnostics.CodeAnalysis; 7 | global using Xunit; 8 | 9 | global using CommunityToolkit.Datasync.Common.Test; 10 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.EntityFrameworkCore.Test/LiveTestsCollection.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Server.EntityFrameworkCore.Test; 6 | 7 | /// 8 | /// This can be used to share state between the various live tests. It isn't used right now. 9 | /// 10 | public class DatabaseFixture 11 | { 12 | 13 | } 14 | 15 | [CollectionDefinition("LiveTestsCollection", DisableParallelization = true)] 16 | public class LiveTestsCollection : ICollectionFixture 17 | { 18 | // This class has no code, and is never created. Its purpose is simply 19 | // to be the place to apply [CollectionDefinition] and all the 20 | // ICollectionFixture<> interfaces. 21 | } 22 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.InMemory.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | global using FluentAssertions; 6 | global using System.Diagnostics.CodeAnalysis; 7 | global using Xunit; -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.InMemory.Test/InMemoryTableData_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Common.Test; 6 | using CommunityToolkit.Datasync.TestCommon; 7 | 8 | namespace CommunityToolkit.Datasync.Server.InMemory.Test; 9 | 10 | [ExcludeFromCodeCoverage] 11 | public class InMemoryTableData_Tests 12 | { 13 | [Theory, ClassData(typeof(ITableData_TestData))] 14 | public void Equals_Works(ITableData a, ITableData b, bool expected) 15 | { 16 | InMemoryTableData entity_a = a.ToTableEntity(); 17 | InMemoryTableData entity_b = b.ToTableEntity(); 18 | 19 | entity_a.Equals(entity_b).Should().Be(expected); 20 | entity_b.Equals(entity_a).Should().Be(expected); 21 | 22 | entity_a.Equals(null).Should().BeFalse(); 23 | entity_b.Equals(null).Should().BeFalse(); 24 | } 25 | } -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.LiteDb.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | global using FluentAssertions; 6 | global using System.Diagnostics.CodeAnalysis; 7 | global using Xunit; 8 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.LiteDb.Test/LiteDbTableData_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Common.Test; 6 | using CommunityToolkit.Datasync.TestCommon; 7 | 8 | namespace CommunityToolkit.Datasync.Server.LiteDb.Test; 9 | 10 | [ExcludeFromCodeCoverage] 11 | public class LiteDbTableData_Tests 12 | { 13 | [Theory, ClassData(typeof(ITableData_TestData))] 14 | public void Equals_Works(ITableData a, ITableData b, bool expected) 15 | { 16 | LiteDbTableData entity_a = a.ToTableEntity(); 17 | LiteDbTableData entity_b = b.ToTableEntity(); 18 | 19 | entity_a.Equals(entity_b).Should().Be(expected); 20 | entity_b.Equals(entity_a).Should().Be(expected); 21 | 22 | entity_a.Equals(null).Should().BeFalse(); 23 | entity_b.Equals(null).Should().BeFalse(); 24 | } 25 | } -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.MongoDB.Test/CommunityToolkit.Datasync.Server.MongoDB.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | runtime; build; native; contentfiles; analyzers; buildtransitive 9 | all 10 | 11 | 12 | runtime; build; native; contentfiles; analyzers; buildtransitive 13 | all 14 | 15 | 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | all 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.MongoDB.Test/MongoTableData_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Common.Test; 6 | using CommunityToolkit.Datasync.TestCommon; 7 | using FluentAssertions; 8 | using Xunit; 9 | 10 | namespace CommunityToolkit.Datasync.Server.MongoDB.Test; 11 | 12 | [ExcludeFromCodeCoverage] 13 | public class MongoTableData_Tests 14 | { 15 | [Theory, ClassData(typeof(ITableData_TestData))] 16 | public void Equals_Works(ITableData a, ITableData b, bool expected) 17 | { 18 | MongoTableData entity_a = a.ToTableEntity(); 19 | MongoTableData entity_b = b.ToTableEntity(); 20 | 21 | entity_a.Equals(entity_b).Should().Be(expected); 22 | entity_b.Equals(entity_a).Should().Be(expected); 23 | 24 | entity_a.Equals(null).Should().BeFalse(); 25 | entity_b.Equals(null).Should().BeFalse(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.NSwag.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | global using FluentAssertions; 6 | global using System.Diagnostics.CodeAnalysis; 7 | global using Xunit; 8 | 9 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.NSwag.Test/Service/ServiceDbContext.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.TestCommon.Databases; 6 | using Microsoft.EntityFrameworkCore; 7 | 8 | namespace CommunityToolkit.Datasync.Server.NSwag.Test.Service; 9 | 10 | [ExcludeFromCodeCoverage] 11 | public class ServiceDbContext(DbContextOptions options) : DbContext(options) 12 | { 13 | public DbSet KitchenSinks => Set(); 14 | public DbSet TodoItems => Set(); 15 | 16 | public void InitializeDatabase() 17 | { 18 | bool created = Database.EnsureCreated(); 19 | if (created && Database.IsSqlite()) 20 | { 21 | this.EnableSqliteExtensions(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.OpenApi.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | global using FluentAssertions; 6 | global using System.Diagnostics.CodeAnalysis; 7 | global using Xunit; 8 | 9 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.OpenApi.Test/Service/ServiceDbContext.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.TestCommon.Databases; 6 | using Microsoft.EntityFrameworkCore; 7 | 8 | namespace CommunityToolkit.Datasync.Server.OpenApi.Test.Service; 9 | 10 | [ExcludeFromCodeCoverage] 11 | public class ServiceDbContext(DbContextOptions options) : DbContext(options) 12 | { 13 | public DbSet KitchenSinks => Set(); 14 | public DbSet TodoItems => Set(); 15 | 16 | public void InitializeDatabase() 17 | { 18 | bool created = Database.EnsureCreated(); 19 | if (created && Database.IsSqlite()) 20 | { 21 | this.EnableSqliteExtensions(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.Swashbuckle.Test/Service/ServiceDbContext.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.TestCommon.Databases; 6 | using Microsoft.EntityFrameworkCore; 7 | 8 | namespace CommunityToolkit.Datasync.Server.Swashbuckle.Test.Service; 9 | 10 | [ExcludeFromCodeCoverage] 11 | public class ServiceDbContext(DbContextOptions options) : DbContext(options) 12 | { 13 | public DbSet KitchenSinks => Set(); 14 | public DbSet TodoItems => Set(); 15 | 16 | public void InitializeDatabase() 17 | { 18 | bool created = Database.EnsureCreated(); 19 | if (created && Database.IsSqlite()) 20 | { 21 | this.EnableSqliteExtensions(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.Test/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | global using FluentAssertions; 6 | global using System.Diagnostics.CodeAnalysis; 7 | global using Xunit; 8 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.Test/Helpers/Extensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.Server.Test; 6 | 7 | [ExcludeFromCodeCoverage] 8 | internal static class ListExtensions 9 | { 10 | internal static void AddIf(this List source, bool shouldBeAdded, T item) 11 | { 12 | if (shouldBeAdded) 13 | { 14 | source.Add(item); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.Test/Models/DatasyncServiceOptions_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Text.Json; 6 | 7 | namespace CommunityToolkit.Datasync.Server.Test.Json; 8 | 9 | [ExcludeFromCodeCoverage] 10 | public class DatasyncServiceOptions_Tests 11 | { 12 | [Fact] 13 | public void JsonSerializerOptions_Works() 14 | { 15 | JsonSerializerOptions options = new DatasyncServiceOptions().JsonSerializerOptions; 16 | options.Should().NotBeNull(); 17 | options.Converters.Should().NotBeNullOrEmpty(); 18 | options.PropertyNamingPolicy.Should().Be(JsonNamingPolicy.CamelCase); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.Server.Test/OData/GeospatialFunctions_Tests.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server.OData; 6 | using Microsoft.Spatial; 7 | 8 | namespace CommunityToolkit.Datasync.Server.Test.OData; 9 | 10 | [ExcludeFromCodeCoverage] 11 | public class GeospatialFunctions_Tests 12 | { 13 | [Fact] 14 | public void GeoDistance_NullArg_ReturnsNaN() 15 | { 16 | GeographyPoint p0 = null; 17 | GeographyPoint p1 = GeographyPoint.Create(0, 0); 18 | 19 | GeospatialFunctions.GeoDistance(p0, p1).Should().Be(double.NaN); 20 | GeospatialFunctions.GeoDistance(p1, p0).Should().Be(double.NaN); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestCommon/Databases/Client/ClientObject.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Text.Json.Serialization; 6 | 7 | namespace CommunityToolkit.Datasync.TestCommon.Databases; 8 | 9 | [ExcludeFromCodeCoverage] 10 | public class ClientObject 11 | { 12 | [JsonExtensionData] 13 | public Dictionary Data { get; set; } = []; 14 | } 15 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestCommon/Databases/ConnectionStrings.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.TestCommon.Databases; 6 | 7 | [ExcludeFromCodeCoverage] 8 | public static class ConnectionStrings 9 | { 10 | public static readonly string CosmosDb = Environment.GetEnvironmentVariable("COSMOS_CONNECTION_STRING"); 11 | public static readonly string CosmosMongo = Environment.GetEnvironmentVariable("MONGO_CONNECTION_STRING"); 12 | public static readonly string Service = Environment.GetEnvironmentVariable("SERVICE_ENDPOINT"); 13 | public static readonly bool EnableLogging = (Environment.GetEnvironmentVariable("ENABLE_SQL_LOGGING") ?? "false") == "true"; 14 | } -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestCommon/Fixtures/MySqlTestFixture.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/Datasync/e6290ecf58d0852a13ffeba38d1a67bf2d66bca6/tests/CommunityToolkit.Datasync.TestCommon/Fixtures/MySqlTestFixture.cs -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestCommon/Models/Country.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.TestCommon.Models; 6 | 7 | /// 8 | /// The model returned by the method. 9 | /// 10 | [ExcludeFromCodeCoverage] 11 | public class Country 12 | { 13 | /// 14 | /// The 2-letter ISO code for the country. 15 | /// 16 | public string IsoCode { get; set; } = string.Empty; 17 | 18 | /// 19 | /// The official name of the country. 20 | /// 21 | public string CountryName { get; set; } = string.Empty; 22 | 23 | /// 24 | /// The latitude of the country's capital city. 25 | /// 26 | public double Latitude { get; set; } 27 | 28 | /// 29 | /// The longitude of the country's capital city. 30 | /// 31 | public double Longitude { get; set; } 32 | } 33 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestCommon/Models/PageOfItems.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Datasync.TestCommon.Models; 6 | 7 | /// 8 | /// The deserialized content from a paging operation. 9 | /// 10 | /// The type of entity being transmitted 11 | [ExcludeFromCodeCoverage] 12 | public class PageOfItems where T : class 13 | { 14 | public T[] Items { get; set; } 15 | public long? Count { get; set; } 16 | public string NextLink { get; set; } 17 | } 18 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestCommon/Models/TableData.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server; 6 | 7 | namespace CommunityToolkit.Datasync.TestCommon.Models; 8 | 9 | /// 10 | /// A concrete implementation of the interface for testing purposes. 11 | /// 12 | [ExcludeFromCodeCoverage] 13 | public class TableData : ITableData 14 | { 15 | /// 16 | public string Id { get; set; } = string.Empty; 17 | 18 | /// 19 | public bool Deleted { get; set; } = false; 20 | 21 | /// 22 | public DateTimeOffset? UpdatedAt { get; set; } = DateTimeOffset.UnixEpoch; 23 | 24 | /// 25 | public byte[] Version { get; set; } = []; 26 | 27 | public bool Equals(ITableData other) 28 | => other is not null && Id == other.Id && Version.SequenceEqual(other.Version); 29 | } 30 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestService/Controllers/AuthorizedMovieController.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server; 6 | using CommunityToolkit.Datasync.TestCommon.Databases; 7 | using Microsoft.AspNetCore.Mvc; 8 | 9 | namespace CommunityToolkit.Datasync.TestService.Controllers; 10 | 11 | [ExcludeFromCodeCoverage] 12 | [Route("api/authorized/movies")] 13 | public class AuthorizedMovieController : TableController 14 | { 15 | public AuthorizedMovieController(IRepository repository, IAccessControlProvider provider) : base(repository) 16 | { 17 | AccessControlProvider = provider; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestService/Controllers/InMemoryKitchenSinkController.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server; 6 | using CommunityToolkit.Datasync.TestCommon.Databases; 7 | using Microsoft.AspNetCore.Mvc; 8 | 9 | namespace CommunityToolkit.Datasync.TestService.Controllers; 10 | 11 | [ExcludeFromCodeCoverage] 12 | [Route("api/in-memory/kitchensink")] 13 | public class InMemoryKitchenSinkController(IRepository repository) : TableController(repository) 14 | { 15 | } -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestService/Controllers/InMemoryMovieController.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server; 6 | using CommunityToolkit.Datasync.TestCommon.Databases; 7 | using Microsoft.AspNetCore.Mvc; 8 | 9 | namespace CommunityToolkit.Datasync.TestService.Controllers; 10 | 11 | [ExcludeFromCodeCoverage] 12 | [Route("api/in-memory/movies")] 13 | public class InMemoryMovieController(IRepository repository) : TableController(repository) 14 | { 15 | } 16 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestService/Controllers/InMemoryPagedMovieController.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server; 6 | using CommunityToolkit.Datasync.TestCommon.Databases; 7 | using Microsoft.AspNetCore.Mvc; 8 | 9 | namespace CommunityToolkit.Datasync.TestService.Controllers; 10 | 11 | [ExcludeFromCodeCoverage] 12 | [Route("api/in-memory/pagedmovies")] 13 | public class InMemoryPagedMovieController : TableController 14 | { 15 | public InMemoryPagedMovieController(IRepository repository) : base(repository) 16 | { 17 | Options = new TableControllerOptions { PageSize = 25 }; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestService/Controllers/InMemorySoftDeletedMovieController.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Datasync.Server; 6 | using CommunityToolkit.Datasync.TestCommon.Databases; 7 | using Microsoft.AspNetCore.Mvc; 8 | 9 | namespace CommunityToolkit.Datasync.TestService.Controllers; 10 | 11 | [ExcludeFromCodeCoverage] 12 | [Route("api/in-memory/softmovies")] 13 | public class InMemorySoftDeletedMovieController : TableController 14 | { 15 | public InMemorySoftDeletedMovieController(IRepository repository) : base(repository) 16 | { 17 | Options.EnableSoftDelete = true; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestService/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "http": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "launchUrl": "api/in-memory/movies", 9 | "applicationUrl": "http://localhost:5082", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | }, 14 | "https": { 15 | "commandName": "Project", 16 | "dotnetRunMessages": true, 17 | "launchBrowser": true, 18 | "launchUrl": "api/in-memory/movies", 19 | "applicationUrl": "https://localhost:5001;http://localhost:5082", 20 | "environmentVariables": { 21 | "ASPNETCORE_ENVIRONMENT": "Development" 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestService/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Datasync.TestService/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | --------------------------------------------------------------------------------