{"id":13409805,"url":"https://github.com/iluvadev/PocketBaseClient","last_synced_at":"2025-03-14T15:30:51.150Z","repository":{"id":64463559,"uuid":"570123610","full_name":"iluvadev/PocketBaseClient","owner":"iluvadev","description":"C# client to interact with a particular PocketBase application: an ORM mapped to your PocketBase server. [This project is in active development. The things described below could change]","archived":false,"fork":false,"pushed_at":"2024-05-18T13:08:33.000Z","size":2732,"stargazers_count":26,"open_issues_count":10,"forks_count":6,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-05-23T07:00:10.517Z","etag":null,"topics":["code-generation","csharp","mapper","netcore","orm","orm-framework","pocketbase"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iluvadev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":["https://www.buymeacoffee.com/iluvadev","Buy me a coffe"]}},"created_at":"2022-11-24T11:47:57.000Z","updated_at":"2024-06-16T11:47:26.483Z","dependencies_parsed_at":"2024-06-16T11:47:16.022Z","dependency_job_id":"d4bc9fa7-0fd2-41b0-9bfc-28988a8bf43e","html_url":"https://github.com/iluvadev/PocketBaseClient","commit_stats":null,"previous_names":["iluvadev/pocketbaseclient-csharp"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iluvadev%2FPocketBaseClient","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iluvadev%2FPocketBaseClient/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iluvadev%2FPocketBaseClient/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iluvadev%2FPocketBaseClient/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iluvadev","download_url":"https://codeload.github.com/iluvadev/PocketBaseClient/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221236246,"owners_count":16782328,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["code-generation","csharp","mapper","netcore","orm","orm-framework","pocketbase"],"created_at":"2024-07-30T20:01:03.465Z","updated_at":"2024-10-26T00:31:06.458Z","avatar_url":"https://github.com/iluvadev.png","language":"C#","readme":"This project is in active development. Things described bellow could change.\n\n# PocketBaseClient\n\nWith **PocketBaseClient** and the code generated for your application with [pbcodegen](doc/pbcodegen.md), you can interact with your [PocketBase](https://pocketbase.io) server without having to worry about communication, APIs, object binding, cache management, etc.\n\nIt is an ORM connected to your PocketBase server with your application.\n\nYou will be able to do things like:\n\n```csharp\nvar myApp = new MyTodoListApplication(); // Binding to PocketBase 'my-todo-list' application\nvar myData = myApp.Data; // The data of the application\n\nvar tasks = myData.TasksCollection; // Collection \"tasks\"\n\n// Iterate over entire collection\nforeach (var task in tasks)\n    Console.WriteLine($\"{task.Title} ({task.Status}): {task.Description}\");\n\n// Filter your data: Paused tasks updated long time ago\nvar oldPausedTasks = tasks.Filter(t =\u003e t.Status.Equal(Task.StatusEnum.Paused).And(\n                                            t.Updated.LessThan(DateTime.Now.AddMonths(-1))));\n\n// Find an element\nvar users = myData.UsersCollection; // Collection \"users\"\nvar me = users.GetById(\"qwertyuiop\");\n\n// Modify your elements\nforeach (var oldPausedTask in oldPausedTasks)\n{\n    oldPausedTask.Status = Task.StatusEnum.ToDo; // Status is an Enum (type select)\n    oldPausedTask.AssignedTo = me;  // AssignedTo is an User (type relation)\n}\n\n// Create a new element\nvar newTask = new Task\n{\n    Title = \"A new Task\",\n    Description = \"Lorem ipsum...\",\n    Status = Task.StatusEnum.ToDo,\n};\n\n// Save all changes to PocketBase (also new elements)\nmyData.SaveChanges();\n```\n\nPocketBaseClient is a Client library in C# for interacting with a particular PocketBase application: It maps all the PocketBase Collections and Registries to Objects and structures to work in c#\n\nSet up an ORM to access your PocketBase application data in less than 1 minute with pbcodegen, the **PocketBaseClient CodeGenerator**\n\n* [PocketBaseClient](#pocketbaseclient)\n* [Installation](#installation)\n* [Overview](#overview)\n  * [Code Generator](#code-generator)\n  * [What PocketBaseClient can do](#what-pocketbaseclient-can-do)\n  * [How it works](#how-it-works)\n    * [Collections and Model Registries](#collections-and-model-registries)\n    * [Cache](#cache)\n  * [Methods and Properties](#methods-and-properties)\n    * [Collections](#collections)\n    * [Object Models](#object-models)\n      * [Object Metadata](#object-metadata)\n  * [Querying](#querying)\n* [Usage](#usage)\n\n# Installation\n\nThe only thing that you need is [pbcodegen](doc/pbcodegen.md). Download the latest version from the [Releases section](https://github.com/iluvadev/PocketBaseClient-csharp/releases), and follow the process.\n\nIn less than 1 minute you will have a customized ORM in c# for your PocketBase application, your own PocketBaseClient.\n\nMore information in [pbcodegen](doc/pbcodegen.md)\n\n# Overview\n\n## Code Generator\n\n[**pbcodegen**](doc/pbcodegen.md) generates your PocketBaseClient, the ORM for your PocketBase application in less than 1 munute: \n\nIt connects to your PocketBase (with admin rights) and generates a c# project for you, with all the logic for the management of comunications with server and  persistence of objects. Exposes custom classes and structures that maps to your Collections and Registries.\n\nIn your .NET projects, you will only need a reference to this generated project to access your PocketBase application.\n\nSee more information in [pbcodegen](doc/pbcodegen.md)\n\n## What PocketBaseClient can do\n\nPocketBaseClient uses the classes generated to map data and operate with a particular PocketBase application: \n\n1. Creating enums for fields of type \"*Select*\".\n\n2. Assigning validation rules for all fields with restrictions.\n\n3. Mapping related registry Ids to relations between objects.\n\n4. Managing the comunication with PocketBase server.\n\n5. Caching objects in memory to minimize the api calls.\n\n6. Getting unknown object data from server when needed (lazy load).\n\n7. Registering changed objects that are in memory and not updated to server.\n\n8. Registering new objects in memory that will map to a new registry in the server. \n\n9. Exposing a simple fluent Filter adapted to the objects\n\n10. CRUD options with objects\n\n11. ...\n\nIs a real ORM for a concrete PocketBase application.\n\nOk, it sounds good, but, how really works?\n\n## How it works\n\nThe magic happens at the junction of PocketBaseClient library and the code generated with *PocketBaseClient.CodeGenerator*:\n\n- Every Collection has its own class with internal cache for its Registries\n\n- Registries have their own class, mapping fields to properties\n\n- Each Registry field is mapped to the correct type, enum or class\n\n### Collections and Model Registries\n\nEach collection has its own class, and internally mantains a cache for its objects. Every object in a Collection is (or will be) a Registry in the mapped PocketBase Collection.\n\nEvery registry belongs to a Collection. This is translated as every Modeled object belongs to a Collection: also new ones (that are only in memory, without a Registry in the server yet).\n\nWhen is created a new object that would become a Registry in PocketBase, it is registered automatically to the correct Collection.\n\nEvery change in an object that maps to a registry, marks the object as \"modified\".\n\nThe changes in memory of the objects can be discarded or saved.\n\nThere is only a function `Save` to save objects to server, it does not matter if the Registry is to be created, updated or deleted in PocketBase.\n\n### Cache\n\nEvery time a Registry is downloaded from PocketBase, it will be mapped as an object and cached. \n\nThe new objects are also cached: they live in memory until they are saved to PocketBase.\n\nThe deleted objects are marked as \"to be deleted in PocketBase\"\n\nWhen an element is requested, by default PocketBaseClient will try to serve it from memory and if it is not cached, from server. This behavior can be modified at every call.\n\n## Methods and Properties\n\nThere are a lot of properties and methods in any modeled object:\n\n### Collections\n\n- Information about the Collection (properties `Id`, `Name` and `System`)\n\n- Get all elements of the collection (enumerate over the collection, implements `IEnumerable\u003cT\u003e`, or use the method `GetItems`)\n\n- Get an element by Id (methods `GetById` and `GetByIdAsync`)\n\n- Check if contains an element (method `Contains`)\n\n- Delete an element (method `Delete`)\n\n- Save to server all changes in the collection and its elements (create, update or delete) (methods `SaveChanges`, `SaveChangesAsync`)\n\n- Discard changes in the collection that are not saved to server (method `DiscardChanges`)\n\n- Query elements (property `Filter`). This will be explained below\n\n### Object Models\n\n* Each field has its own Property with the correct type\n\n* Information about collection (properties `Collection`, `CollectionId` and `CollectionName`)\n\n* Information about the object status (property `Metadata_`, see [Object Metadata](#object-metadata))\n\n* Validate object data (method `Validate` or properties `Metadata_.IsValid` and `Metadata_.ValidationErrors`)\n\n* Reload the object with data in server (methods `Reload` and `ReloadAsync`)\n\n* Delete the element (method `Delete`)\n\n* Discard local changes of the object (method `DiscardChanges`)\n\n* Save element to server (create or update) (methods `Save` and `SaveAsync`)\n\n* Check if two objects references the same registry (method `IsSame`)\n\n* Update the object with data of other (method `UpdateWith`)\n\n#### Object Metadata\n\nContains properties with information about the object:\n\n* Validation:  `IsValid`, `ValidationErrors`\n\n* Changes:  `HasLocalChanges`, `FirstChange`, `LastChange`\n\n* Status: `IsCached`, `IsLoaded`, `IsNew`, `IsTobeDeleted`, `IsTrash`, `SyncStatus`\n\n## Querying\n\n(Documentation incomplete)\n\n# Usage\n\nSupose this PocketBase Schema of an application with name '`my-todo-list`':\n\n```\n ┌──────────────────┐       ┌──────────────────┐\n │ todo_lists       │       │ tasks            │       ┌────────────────┐\n ├──────────────────┤       ├──────────────────┤       │ priorities     │\n │ name        :T   │       │ title       :T   │       ├────────────────┤\n │ description :T   │     N │ description :T   │     1 │ name        :T │\n │ tasks       :Rel -------\u003e│ priority    :Rel -------\u003e│ value       :# │\n └──────────────────┘       │ status      :Sel │       │ description :T │\n                            │     │to do       │       └────────────────┘\n                            │     │doing       │\n                            │     │paused      │\n                            │     │done        │\n                            └──────────────────┘\n```\n\nWith [pbcodegen](doc/pbcodegen.md) you can generate the Model and it can be used as:\n\n```csharp\n// 'my-todo-list' application\nvar myApp = new MyTodoListApplication(); \n\n// The data of the application\nvar myData = myApp.Data;\n\n// Print all todo_lists registries:\nforeach (var todoList in myData.TodoListsCollection)\n{\n   Console.WriteLine($\"{todoList.Name} ({todoList.Description})\");\n   foreach (var task in todoList.Tasks)\n   {\n      Console.WriteLine($\"   - {task.Title} ({task.Description})\");\n      Console.WriteLine($\"     {task.Priority.Name}\");\n      Console.WriteLine($\"     {task.Status}\");\n      if (task.Status == Task.StatusEnum.Done)\n         Console.WriteLine(\"Well done!!\");\n   }\n}\n\n// Filter over tasks collection in PocketBase (filter in server)\nvar oldPausedTasks = tasks.Filter(t =\u003e t.Status.Equal(Task.StatusEnum.Paused).And(\n                                            t.Updated.LessThan(DateTime.Now.AddMonths(-1))));\n\n\n// Use Linq (in-memory: intenal cache or get registries from server if needed)\nvar myTodoLists = myData.TodoListsCollection.Where(t =\u003e t.Name.Contains(\"my todo list\"));\n\nvar allPriorities = myData.PrioritiesCollection;\n\n// Getting by Id\nvar myList = myData.TodoListsCollection.GetById(\"qwertyuiop\");\n// Creating a new Task (it will be a registry in 'tasks' collection)\nvar newTask = new Task\n{\n   Title = \"My Title\",\n   Description = \"My Description\",\n   Priority = allPriorities.OrderByDescending(p =\u003e p.Value).First(),\n   Status = Task.StatusEnum.ToDo\n};\n// Add it in the Tasks list (it will modify the 'tasks' field)\nmyList.Tasks.Add(newTask);\n\n// Now, the changes are only in memory\n\n// Save the todo_list (and its tasks)\nmyList.Save();\n\n// Or save all todo_lists\nmyData.TodoListsCollection.SaveChanges();\n\n//Or save all changes in all collections\nmyData.SaveChanges();\n\n// Now, the changes are saved to PocketBase\n```\n\n(Documentation incomplete)\n","funding_links":["https://www.buymeacoffee.com/iluvadev","Buy me a coffe"],"categories":["C#"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filuvadev%2FPocketBaseClient","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Filuvadev%2FPocketBaseClient","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filuvadev%2FPocketBaseClient/lists"}