@chill-sharp/ui-core 1.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/.agents/skills/chillsharp-current-user-preferences/SKILL.md +70 -0
  2. package/.agents/skills/chillsharp-ui-template/SKILL.md +18 -0
  3. package/README.md +103 -0
  4. package/chill-sharp-ui-core.d.ts.map +1 -0
  5. package/doc/AIAssistedDevelopment/README.md +185 -0
  6. package/doc/AttachmentModel/README.md +173 -0
  7. package/doc/AuthenticationModel/README.md +213 -0
  8. package/doc/AuthenticationModel/how-to-integreate-auth-minimal-api.md +293 -0
  9. package/doc/ChillSharpClient.md +464 -0
  10. package/doc/ClientGeneration/README.md +172 -0
  11. package/doc/ComplianceGuide/README.md +178 -0
  12. package/doc/Configuration/README.md +94 -0
  13. package/doc/CurrentUserPreferences.md +114 -0
  14. package/doc/DateTimePolicy/README.md +154 -0
  15. package/doc/DateTimeSerialization.md +423 -0
  16. package/doc/Endpoints.md +260 -0
  17. package/doc/HowTo/01-simple-blog-sqlite.md +153 -0
  18. package/doc/HowTo/02-blog-schema-labels.md +140 -0
  19. package/doc/HowTo/03-authentication.md +218 -0
  20. package/doc/HowTo/04-blog-posts-one-to-many.md +194 -0
  21. package/doc/HowTo/05-docker-env-variables.md +274 -0
  22. package/doc/HowTo/06-chunk-transactions-autocomplete.md +196 -0
  23. package/doc/Mcp/ChatGPT.md +291 -0
  24. package/doc/Mcp/README.md +799 -0
  25. package/doc/MenuGuide/README.md +49 -0
  26. package/doc/ModelPreparation.md +255 -0
  27. package/doc/PermissionModel/README.md +277 -0
  28. package/doc/README.md +228 -0
  29. package/doc/ReferenceExistence.md +130 -0
  30. package/doc/RegisterContext.md +217 -0
  31. package/doc/UiCore/CRUD.md +170 -0
  32. package/doc/UiCore/README.md +13 -0
  33. package/doc/ValidationModel/README.md +117 -0
  34. package/doc/it/AIAssistedDevelopment/README.md +185 -0
  35. package/doc/it/AttachmentModel/README.md +173 -0
  36. package/doc/it/AuthenticationModel/README.md +171 -0
  37. package/doc/it/AuthenticationModel/how-to-integreate-auth-minimal-api.md +292 -0
  38. package/doc/it/ChillSharpClient.md +464 -0
  39. package/doc/it/ClientGeneration/README.md +152 -0
  40. package/doc/it/ComplianceGuide/README.md +178 -0
  41. package/doc/it/Configuration/README.md +94 -0
  42. package/doc/it/CurrentUserPreferences.md +114 -0
  43. package/doc/it/DateTimePolicy/README.md +154 -0
  44. package/doc/it/DateTimeSerialization.md +423 -0
  45. package/doc/it/Endpoints.md +260 -0
  46. package/doc/it/HowTo/01-simple-blog-sqlite.md +152 -0
  47. package/doc/it/HowTo/02-blog-schema-labels.md +139 -0
  48. package/doc/it/HowTo/03-authentication.md +221 -0
  49. package/doc/it/HowTo/04-blog-posts-one-to-many.md +193 -0
  50. package/doc/it/HowTo/05-docker-env-variables.md +268 -0
  51. package/doc/it/HowTo/06-chunk-transactions-autocomplete.md +196 -0
  52. package/doc/it/Mcp/ChatGPT.md +291 -0
  53. package/doc/it/Mcp/README.md +799 -0
  54. package/doc/it/MenuGuide/README.md +49 -0
  55. package/doc/it/ModelPreparation.md +254 -0
  56. package/doc/it/PermissionModel/README.md +190 -0
  57. package/doc/it/README.md +172 -0
  58. package/doc/it/ReferenceExistence.md +130 -0
  59. package/doc/it/RegisterContext.md +218 -0
  60. package/doc/it/UiCore/CRUD.md +170 -0
  61. package/doc/it/UiCore/README.md +13 -0
  62. package/doc/it/ValidationModel/README.md +117 -0
  63. package/fesm2022/chill-sharp-ui-core.mjs +16725 -0
  64. package/fesm2022/chill-sharp-ui-core.mjs.map +1 -0
  65. package/index.d.ts +6 -0
  66. package/lib/chill-sharp-ui-root.component.d.ts +6 -0
  67. package/lib/chill-sharp-ui-root.component.d.ts.map +1 -0
  68. package/lib/chill-sharp-ui.routes.d.ts +3 -0
  69. package/lib/chill-sharp-ui.routes.d.ts.map +1 -0
  70. package/lib/chill.config.d.ts +5 -0
  71. package/lib/chill.config.d.ts.map +1 -0
  72. package/lib/layouts/auth-shell.component.d.ts +8 -0
  73. package/lib/layouts/auth-shell.component.d.ts.map +1 -0
  74. package/lib/layouts/workspace-page.component.d.ts +49 -0
  75. package/lib/layouts/workspace-page.component.d.ts.map +1 -0
  76. package/lib/lib/chill-form.component.d.ts +151 -0
  77. package/lib/lib/chill-form.component.d.ts.map +1 -0
  78. package/lib/lib/chill-i18n-button-label.component.d.ts +27 -0
  79. package/lib/lib/chill-i18n-button-label.component.d.ts.map +1 -0
  80. package/lib/lib/chill-i18n-label.component.d.ts +30 -0
  81. package/lib/lib/chill-i18n-label.component.d.ts.map +1 -0
  82. package/lib/lib/chill-json-input.component.d.ts +31 -0
  83. package/lib/lib/chill-json-input.component.d.ts.map +1 -0
  84. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-boolean-control.component.d.ts +12 -0
  85. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-boolean-control.component.d.ts.map +1 -0
  86. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-editor-control.component.d.ts +17 -0
  87. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-editor-control.component.d.ts.map +1 -0
  88. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-lookup-control.component.d.ts +45 -0
  89. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-lookup-control.component.d.ts.map +1 -0
  90. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-scalar-control.component.d.ts +19 -0
  91. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-scalar-control.component.d.ts.map +1 -0
  92. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-select-control.component.d.ts +12 -0
  93. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-select-control.component.d.ts.map +1 -0
  94. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-textarea-control.component.d.ts +13 -0
  95. package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-textarea-control.component.d.ts.map +1 -0
  96. package/lib/lib/chill-polymorphic-input.component.d.ts +452 -0
  97. package/lib/lib/chill-polymorphic-input.component.d.ts.map +1 -0
  98. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-boolean-control.component.d.ts +7 -0
  99. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-boolean-control.component.d.ts.map +1 -0
  100. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-lookup-control.component.d.ts +7 -0
  101. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-lookup-control.component.d.ts.map +1 -0
  102. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-number-control.component.d.ts +7 -0
  103. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-number-control.component.d.ts.map +1 -0
  104. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-temporal-control.component.d.ts +8 -0
  105. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-temporal-control.component.d.ts.map +1 -0
  106. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-value-control.component.d.ts +7 -0
  107. package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-value-control.component.d.ts.map +1 -0
  108. package/lib/lib/chill-polymorphic-output.component.d.ts +75 -0
  109. package/lib/lib/chill-polymorphic-output.component.d.ts.map +1 -0
  110. package/lib/lib/chill-table.component.d.ts +434 -0
  111. package/lib/lib/chill-table.component.d.ts.map +1 -0
  112. package/lib/lib/chill-text-editor-dialog.component.d.ts +14 -0
  113. package/lib/lib/chill-text-editor-dialog.component.d.ts.map +1 -0
  114. package/lib/lib/crud-configuration.utils.d.ts +4 -0
  115. package/lib/lib/crud-configuration.utils.d.ts.map +1 -0
  116. package/lib/lib/culture-name-options.d.ts +3 -0
  117. package/lib/lib/culture-name-options.d.ts.map +1 -0
  118. package/lib/lib/date-format-options.d.ts +3 -0
  119. package/lib/lib/date-format-options.d.ts.map +1 -0
  120. package/lib/lib/iana-time-zone-options.d.ts +3 -0
  121. package/lib/lib/iana-time-zone-options.d.ts.map +1 -0
  122. package/lib/lib/notice-transition.directive.d.ts +17 -0
  123. package/lib/lib/notice-transition.directive.d.ts.map +1 -0
  124. package/lib/lib/schema-property-dialog.component.d.ts +74 -0
  125. package/lib/lib/schema-property-dialog.component.d.ts.map +1 -0
  126. package/lib/models/chill-auth.models.d.ts +176 -0
  127. package/lib/models/chill-auth.models.d.ts.map +1 -0
  128. package/lib/models/chill-menu.models.d.ts +12 -0
  129. package/lib/models/chill-menu.models.d.ts.map +1 -0
  130. package/lib/models/chill-schema.models.d.ts +141 -0
  131. package/lib/models/chill-schema.models.d.ts.map +1 -0
  132. package/lib/models/workspace-dialog.models.d.ts +16 -0
  133. package/lib/models/workspace-dialog.models.d.ts.map +1 -0
  134. package/lib/models/workspace-task.models.d.ts +36 -0
  135. package/lib/models/workspace-task.models.d.ts.map +1 -0
  136. package/lib/pages/confirm-reset-page.component.d.ts +21 -0
  137. package/lib/pages/confirm-reset-page.component.d.ts.map +1 -0
  138. package/lib/pages/crud/attachment-upload-dialog.component.d.ts +24 -0
  139. package/lib/pages/crud/attachment-upload-dialog.component.d.ts.map +1 -0
  140. package/lib/pages/crud/crud-page.component.d.ts +244 -0
  141. package/lib/pages/crud/crud-page.component.d.ts.map +1 -0
  142. package/lib/pages/login-page.component.d.ts +21 -0
  143. package/lib/pages/login-page.component.d.ts.map +1 -0
  144. package/lib/pages/permissions/auth-role-dialog.component.d.ts +29 -0
  145. package/lib/pages/permissions/auth-role-dialog.component.d.ts.map +1 -0
  146. package/lib/pages/permissions/auth-search-select.component.d.ts +28 -0
  147. package/lib/pages/permissions/auth-search-select.component.d.ts.map +1 -0
  148. package/lib/pages/permissions/auth-user-dialog.component.d.ts +35 -0
  149. package/lib/pages/permissions/auth-user-dialog.component.d.ts.map +1 -0
  150. package/lib/pages/permissions/permission-editor.component.d.ts +55 -0
  151. package/lib/pages/permissions/permission-editor.component.d.ts.map +1 -0
  152. package/lib/pages/permissions/permissions-page.component.d.ts +38 -0
  153. package/lib/pages/permissions/permissions-page.component.d.ts.map +1 -0
  154. package/lib/pages/permissions/role-permission.component.d.ts +43 -0
  155. package/lib/pages/permissions/role-permission.component.d.ts.map +1 -0
  156. package/lib/pages/permissions/user-permission.component.d.ts +43 -0
  157. package/lib/pages/permissions/user-permission.component.d.ts.map +1 -0
  158. package/lib/pages/register-page.component.d.ts +24 -0
  159. package/lib/pages/register-page.component.d.ts.map +1 -0
  160. package/lib/pages/reset-password-page.component.d.ts +18 -0
  161. package/lib/pages/reset-password-page.component.d.ts.map +1 -0
  162. package/lib/provide-chill-sharp-ui-core.d.ts +8 -0
  163. package/lib/provide-chill-sharp-ui-core.d.ts.map +1 -0
  164. package/lib/services/chill.service.d.ts +249 -0
  165. package/lib/services/chill.service.d.ts.map +1 -0
  166. package/lib/services/workspace-dialog.service.d.ts +22 -0
  167. package/lib/services/workspace-dialog.service.d.ts.map +1 -0
  168. package/lib/services/workspace-layout.service.d.ts +13 -0
  169. package/lib/services/workspace-layout.service.d.ts.map +1 -0
  170. package/lib/services/workspace-task-registry.service.d.ts +35 -0
  171. package/lib/services/workspace-task-registry.service.d.ts.map +1 -0
  172. package/lib/services/workspace-toolbar.service.d.ts +23 -0
  173. package/lib/services/workspace-toolbar.service.d.ts.map +1 -0
  174. package/lib/services/workspace.service.d.ts +114 -0
  175. package/lib/services/workspace.service.d.ts.map +1 -0
  176. package/lib/storage-keys.d.ts +5 -0
  177. package/lib/storage-keys.d.ts.map +1 -0
  178. package/lib/tasks/crud-task/crud-task.component.d.ts +33 -0
  179. package/lib/tasks/crud-task/crud-task.component.d.ts.map +1 -0
  180. package/lib/tasks/goto-url-task/goto-url-task.component.d.ts +31 -0
  181. package/lib/tasks/goto-url-task/goto-url-task.component.d.ts.map +1 -0
  182. package/lib/workspace/confirm-message-dialog.component.d.ts +16 -0
  183. package/lib/workspace/confirm-message-dialog.component.d.ts.map +1 -0
  184. package/lib/workspace/entity-options-dialog.component.d.ts +29 -0
  185. package/lib/workspace/entity-options-dialog.component.d.ts.map +1 -0
  186. package/lib/workspace/external-task-api.d.ts +2 -0
  187. package/lib/workspace/external-task-api.d.ts.map +1 -0
  188. package/lib/workspace/user-profile-dialog.component.d.ts +30 -0
  189. package/lib/workspace/user-profile-dialog.component.d.ts.map +1 -0
  190. package/lib/workspace/workspace-dialog-host.component.d.ts +26 -0
  191. package/lib/workspace/workspace-dialog-host.component.d.ts.map +1 -0
  192. package/lib/workspace/workspace-menu-item-dialog.component.d.ts +61 -0
  193. package/lib/workspace/workspace-menu-item-dialog.component.d.ts.map +1 -0
  194. package/lib/workspace/workspace-menu.component.d.ts +104 -0
  195. package/lib/workspace/workspace-menu.component.d.ts.map +1 -0
  196. package/lib/workspace/workspace-taskbar.component.d.ts +14 -0
  197. package/lib/workspace/workspace-taskbar.component.d.ts.map +1 -0
  198. package/package.json +54 -0
  199. package/public-api.d.ts +56 -0
  200. package/public-api.d.ts.map +1 -0
  201. package/service-worker/chill-sharp-service-worker.js +166 -0
  202. package/styles/core-theme.scss +1268 -0
  203. package/template-customization/upgrade.ps1.template +342 -0
  204. package/template-customization/upgrade.sh.template +271 -0
@@ -0,0 +1,153 @@
1
+ # HOW-TO: Simple Blog API on SQLite
2
+
3
+ Versione italiana: [Italiano](../it/HowTo/01-simple-blog-sqlite.md)
4
+
5
+ This example shows the smallest useful ChillSharp setup: one `Blog` entity, one EF Core SQLite context, and a ChillSharp API with no schema label texts in `ChillEntity` or `ChillProperty` attributes.
6
+
7
+ ## Goal
8
+
9
+ Build a minimal API that can create and read `Blog` entities through ChillSharp.
10
+
11
+ ## 1. Define the entity
12
+
13
+ Use the parameterless versions of `ChillEntity` and `ChillProperty` when you do not want to provide schema texts yet.
14
+
15
+ ```csharp
16
+ using ChillSharp.Annotations;
17
+ using ChillSharp.EF;
18
+ using System.ComponentModel.DataAnnotations;
19
+
20
+ namespace MyBlogApp.Model;
21
+
22
+ [ChillEntity]
23
+ public class Blog : ChillEntity
24
+ {
25
+ [Key]
26
+ public override Guid Guid { get; set; }
27
+
28
+ [ChillProperty]
29
+ public string Name { get; set; } = string.Empty;
30
+
31
+ [ChillProperty]
32
+ public string? Url { get; set; }
33
+
34
+ public override string GetLabel(IChillContext context) => Name;
35
+ }
36
+ ```
37
+
38
+ ## 2. Define a query
39
+
40
+ `Find` is enough to load one entity by `Guid`, but a query type is still useful when you want normal filtering and projections.
41
+
42
+ ```csharp
43
+ using ChillSharp.Annotations;
44
+ using ChillSharp.EF;
45
+
46
+ namespace MyBlogApp.Query;
47
+
48
+ [ChillEntity]
49
+ public class BlogQuery : ChillQuery
50
+ {
51
+ [ChillProperty]
52
+ public string? Name { get; set; }
53
+
54
+ public override IQueryable<IChillEntity> OnQuery(IChillContext context)
55
+ {
56
+ var db = (BloggingContext)context;
57
+ var query = db.Blogs.AsQueryable();
58
+
59
+ if (Guid.HasValue)
60
+ query = query.Where(x => x.Guid == Guid.Value);
61
+
62
+ if (!string.IsNullOrWhiteSpace(Name))
63
+ query = query.Where(x => x.Name.Contains(Name));
64
+
65
+ return query;
66
+ }
67
+ }
68
+ ```
69
+
70
+ ## 3. Create the SQLite context
71
+
72
+ The context must implement `IChillContext` and return the namespace prefix used by your model and query types.
73
+
74
+ ```csharp
75
+ using Microsoft.EntityFrameworkCore;
76
+ using MyBlogApp.Model;
77
+
78
+ namespace MyBlogApp;
79
+
80
+ public class BloggingContext : DbContext, IChillContext
81
+ {
82
+ public DbSet<Blog> Blogs => Set<Blog>();
83
+
84
+ public BloggingContext(DbContextOptions<BloggingContext> options) : base(options)
85
+ {
86
+ }
87
+
88
+ public string GetChillTypePrefix() => "MyBlogApp";
89
+ }
90
+ ```
91
+
92
+ ## 4. Register ChillSharp
93
+
94
+ ```csharp
95
+ using ChillSharp.Api;
96
+ using Microsoft.EntityFrameworkCore;
97
+
98
+ var builder = WebApplication.CreateBuilder(args);
99
+
100
+ builder.Services.AddDbContext<BloggingContext>(options =>
101
+ options.UseSqlite("Data Source=blogging.db"));
102
+
103
+ builder.Services.AddChillApi<BloggingContext>();
104
+
105
+ var app = builder.Build();
106
+
107
+ using (var scope = app.Services.CreateScope())
108
+ {
109
+ var db = scope.ServiceProvider.GetRequiredService<BloggingContext>();
110
+ db.Database.EnsureCreated();
111
+ }
112
+
113
+ app.MapChillApi();
114
+ app.Run();
115
+ ```
116
+
117
+ ## 5. Create and read a blog with `ChillSharpClient`
118
+
119
+ ```csharp
120
+ using ChillSharp.Client;
121
+ using ChillSharp.Client.Dto;
122
+
123
+ var client = new ChillSharpClient("http://localhost:5000/api/chill");
124
+
125
+ var blog = new ChillDtoEntity
126
+ {
127
+ ChillType = "Model.Blog",
128
+ Guid = Guid.NewGuid()
129
+ };
130
+ blog.Properties["Name"] = "SQLite Notes";
131
+ blog.Properties["Url"] = "https://example.local/sqlite-notes";
132
+
133
+ var created = client.Create(blog);
134
+
135
+ var query = new ChillDtoQuery
136
+ {
137
+ ChillType = "Query.BlogQuery"
138
+ };
139
+ query.Properties["Guid"] = created.Guid;
140
+ query.ResultProperties = ChillDtoProperty.Build("Guid", "Name", "Url");
141
+
142
+ var result = client.Query(query);
143
+ var loadedBlog = result.Results.Single();
144
+ Console.WriteLine($"{loadedBlog.GetString("Name")} -> {loadedBlog.GetString("Url")}");
145
+ ```
146
+
147
+ ## Notes
148
+
149
+ - `Model.Blog` and `Query.BlogQuery` are short type names. ChillSharp expands them using `GetChillTypePrefix()`.
150
+ - With parameterless attributes, schema metadata falls back to the CLR type and property names.
151
+
152
+ Next example: [Add schema labels and read them through ChillSharp](02-blog-schema-labels.md)
153
+
@@ -0,0 +1,140 @@
1
+ # HOW-TO: Add Schema Labels to Blog and Read Them
2
+
3
+ Versione italiana: [Italiano](../it/HowTo/02-blog-schema-labels.md)
4
+
5
+ This example updates the previous `Blog` model by adding schema texts to `ChillEntity` and `ChillProperty`, then shows how to read those labels back.
6
+
7
+ ## Goal
8
+
9
+ Decorate the model with schema metadata and retrieve it through ChillSharp schema services.
10
+
11
+ ## 1. Add labels to the entity and properties
12
+
13
+ ```csharp
14
+ using ChillSharp.Annotations;
15
+ using ChillSharp.EF;
16
+ using System.ComponentModel.DataAnnotations;
17
+
18
+ namespace MyBlogApp.Model;
19
+
20
+ [ChillEntity(
21
+ UniquePropertyKeyString: "4E16F6C0-6B95-4D67-98BC-9F4D0D63EAF1",
22
+ PrimaryLanguageLabel: "Blog",
23
+ SecondaryLanguageLabel: "Blog")]
24
+ public class Blog : ChillEntity
25
+ {
26
+ [Key]
27
+ public override Guid Guid { get; set; }
28
+
29
+ [ChillProperty(
30
+ UniquePropertyKeyString: "50B1BB6C-D794-41E4-A85C-D4F9D7A6FA7E",
31
+ PrimaryLanguageLabel: "Blog name",
32
+ SecondaryLanguageLabel: "Nome blog")]
33
+ public string Name { get; set; } = string.Empty;
34
+
35
+ [ChillProperty(
36
+ UniquePropertyKeyString: "A18E7754-D8F7-45FE-B8A8-EA762A4EC9E6",
37
+ PrimaryLanguageLabel: "Blog url",
38
+ SecondaryLanguageLabel: "Url blog")]
39
+ public string? Url { get; set; }
40
+
41
+ public override string GetLabel(IChillContext context) => Name;
42
+ }
43
+ ```
44
+
45
+ ## 2. Enable schema persistence
46
+
47
+ To expose schema metadata through `get-schema`, the EF Core context must also implement `IChillSchemaDbContext`, add the schema model, and register `AddChillSchema<TContext>()`.
48
+
49
+ ```csharp
50
+ using ChillSharp.Schema;
51
+ using ChillSharp.Schema.Model;
52
+ using Microsoft.EntityFrameworkCore;
53
+ using MyBlogApp.Model;
54
+
55
+ namespace MyBlogApp;
56
+
57
+ public class BloggingContext : DbContext, IChillContext, IChillSchemaDbContext
58
+ {
59
+ public DbSet<Blog> Blogs => Set<Blog>();
60
+ public DbSet<ChillSchemaEntry> SchemaEntries => Set<ChillSchemaEntry>();
61
+
62
+ public BloggingContext(DbContextOptions<BloggingContext> options) : base(options)
63
+ {
64
+ }
65
+
66
+ public string GetChillTypePrefix() => "MyBlogApp";
67
+
68
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
69
+ {
70
+ base.OnModelCreating(modelBuilder);
71
+ modelBuilder.AddChillSchemaModel();
72
+ }
73
+ }
74
+ ```
75
+
76
+ Register the schema service together with the API:
77
+
78
+ ```csharp
79
+ using ChillSharp.Api;
80
+ using ChillSharp.Schema;
81
+ using Microsoft.EntityFrameworkCore;
82
+
83
+ var builder = WebApplication.CreateBuilder(args);
84
+
85
+ builder.Services.AddDbContext<BloggingContext>(options =>
86
+ options.UseSqlite("Data Source=blogging.db"));
87
+
88
+ builder.Services.AddChillApi<BloggingContext>();
89
+ builder.Services.AddChillSchema<BloggingContext>();
90
+ ```
91
+
92
+ ## 3. Read schema metadata from a client
93
+
94
+ `ChillSharpClient.GetSchema(...)` returns property metadata generated from the decorated model.
95
+
96
+ ```csharp
97
+ using ChillSharp.Client;
98
+
99
+ var client = new ChillSharpClient("http://localhost:5000/api/chill");
100
+ var schema = client.GetSchema("Model.Blog", "default");
101
+
102
+ var nameProperty = schema?.Properties.Single(x => x.Name == "Name");
103
+ var urlProperty = schema?.Properties.Single(x => x.Name == "Url");
104
+
105
+ Console.WriteLine(nameProperty?.DisplayName); // Blog name
106
+ Console.WriteLine(urlProperty?.DisplayName); // Blog url
107
+ ```
108
+
109
+ ## 4. Read the entity display name in server-side code
110
+
111
+ The server-side `ChillSharp.Dto.ChillDtoSchema` also carries the entity-level `DisplayName`, which is populated from `ChillEntityAttribute.PrimaryLanguageLabel`.
112
+
113
+ ```csharp
114
+ using ChillSharp;
115
+
116
+ public class SchemaDebugService
117
+ {
118
+ private readonly IChillDtoEngine _dtoEngine;
119
+
120
+ public SchemaDebugService(IChillDtoEngine dtoEngine)
121
+ {
122
+ _dtoEngine = dtoEngine;
123
+ }
124
+
125
+ public string? GetBlogSchemaDisplayName()
126
+ {
127
+ var schema = _dtoEngine.GetSchema("Model.Blog", "default");
128
+ return schema?.DisplayName;
129
+ }
130
+ }
131
+ ```
132
+
133
+ ## Notes
134
+
135
+ - Property `DisplayName` comes from `ChillPropertyAttribute.PrimaryLanguageLabel`.
136
+ - Entity `DisplayName` comes from `ChillEntityAttribute.PrimaryLanguageLabel`.
137
+ - If you later call `SetSchema(...)`, persisted schema values can override the generated defaults for a given `ChillType` and `ChillViewCode`.
138
+
139
+ Next example: [Use authentication with ChillSharp](03-authentication.md)
140
+
@@ -0,0 +1,218 @@
1
+ # HOW-TO: Use Authentication with ChillSharp
2
+
3
+ Versione italiana: [Italiano](../it/HowTo/03-authentication.md)
4
+
5
+ This example shows the smallest useful authentication setup for a ChillSharp API: protect the API, enable the auth module, register an account, log in, and let `ChillSharpClient` reuse and refresh tokens automatically.
6
+
7
+ ## Goal
8
+
9
+ Expose a protected ChillSharp API backed by ASP.NET Core Identity and authenticate with `ChillSharpClient`.
10
+
11
+ ## 1. Use a context that supports Identity and ChillSharp auth
12
+
13
+ The context must support your normal ChillSharp model and the auth tables.
14
+
15
+ ```csharp
16
+ using ChillSharp;
17
+ using ChillSharp.Auth;
18
+ using Microsoft.AspNetCore.Identity;
19
+ using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
20
+ using Microsoft.EntityFrameworkCore;
21
+
22
+ namespace MyBlogApp;
23
+
24
+ public class BloggingContext : IdentityDbContext<IdentityUser>, IChillContext, IChillAuthDbContext
25
+ {
26
+ public BloggingContext(DbContextOptions<BloggingContext> options) : base(options)
27
+ {
28
+ }
29
+
30
+ public string GetChillTypePrefix() => "MyBlogApp";
31
+
32
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
33
+ {
34
+ base.OnModelCreating(modelBuilder);
35
+ modelBuilder.AddChillAuthModel();
36
+ }
37
+ }
38
+ ```
39
+
40
+ ## 2. Register Identity, authentication, and ChillSharp auth services
41
+
42
+ Protect the normal ChillSharp API and add the auth endpoints on top of it.
43
+
44
+ ```csharp
45
+ using ChillSharp.Api;
46
+ using ChillSharp.Auth;
47
+ using ChillSharp.Auth.Api;
48
+ using Microsoft.AspNetCore.Identity;
49
+ using Microsoft.EntityFrameworkCore;
50
+
51
+ var builder = WebApplication.CreateBuilder(args);
52
+
53
+ builder.Services.AddDbContext<BloggingContext>(options =>
54
+ options.UseSqlite("Data Source=blogging-auth.db"));
55
+
56
+ builder.Services.AddIdentityCore<IdentityUser>()
57
+ .AddEntityFrameworkStores<BloggingContext>()
58
+ .AddSignInManager()
59
+ .AddDefaultTokenProviders();
60
+
61
+ builder.Services.AddAuthentication(ChillAuthIdentityDefaults.AuthenticationScheme)
62
+ .AddChillAuthBearer();
63
+
64
+ builder.Services.AddAuthorization();
65
+
66
+ builder.Services.AddChillApi<BloggingContext, IdentityUser>(options =>
67
+ {
68
+ options.ProtectedApi = true;
69
+ options.ReturnPasswordResetTokensInResponse = true;
70
+ options.InitializeRootUserOnStartup = true;
71
+ options.CreateChillAuthUserForRoot = true;
72
+ options.RootUserName = "root";
73
+ options.RootPassword = "Pass123$";
74
+ options.RootEmail = "root@example.com";
75
+ options.RootDisplayName = "Root Administrator";
76
+ });
77
+ ```
78
+
79
+ When `CreateChillAuthUserForRoot = true`, startup also creates the linked ChillSharp `AuthUser` and sets `CanManagePermissions = true` for that root user.
80
+
81
+ You can also provide the same bootstrap values through environment variables instead of hardcoding them:
82
+
83
+ ```text
84
+ CHILLSHARP_AUTH_ROOT_USERNAME=root
85
+ CHILLSHARP_AUTH_ROOT_PASSWORD=Pass123$
86
+ CHILLSHARP_AUTH_ROOT_EMAIL=root@example.com
87
+ CHILLSHARP_AUTH_ROOT_DISPLAY_NAME=Root Administrator
88
+ ```
89
+
90
+ ## 3. Enable middleware and map the API
91
+
92
+ `MapChillApi()` exposes both the normal ChillSharp endpoints and the auth endpoints once the auth services are registered.
93
+
94
+ ```csharp
95
+ var app = builder.Build();
96
+
97
+ app.UseAuthentication();
98
+ app.UseAuthorization();
99
+
100
+ using (var scope = app.Services.CreateScope())
101
+ {
102
+ var db = scope.ServiceProvider.GetRequiredService<BloggingContext>();
103
+ db.Database.EnsureCreated();
104
+ }
105
+
106
+ app.MapChillApi();
107
+ app.Run();
108
+ ```
109
+
110
+ ## 4. Use the root user to manage permissions
111
+
112
+ The root-user initializer is the easiest bootstrap path for a new protected system because the linked ChillSharp auth user is created with permission-management enabled.
113
+
114
+ ```csharp
115
+ var rootClient = new ChillSharpClient("http://localhost:5000/api/chill");
116
+
117
+ var rootLogin = rootClient.LoginAuthAccount(new LoginAuthIdentityRequest
118
+ {
119
+ UserNameOrEmail = "root",
120
+ Password = "Pass123$"
121
+ });
122
+
123
+ var authUsers = rootClient.GetAuthUsers();
124
+ Console.WriteLine(authUsers.Count);
125
+ ```
126
+
127
+ That login can call auth-management endpoints such as users, roles, and permission rules because the generated root `AuthUser` has `CanManagePermissions = true`.
128
+
129
+ ## 5. Register the first normal account
130
+
131
+ Create the client with the normal Chill base URL. Auth calls automatically switch from `/api/chill` to `/api/chill-auth`.
132
+
133
+ ```csharp
134
+ using ChillSharp.Auth.Contracts;
135
+ using ChillSharp.Client;
136
+
137
+ var client = new ChillSharpClient("http://localhost:5000/api/chill");
138
+
139
+ var registerResponse = client.RegisterAuthAccount(new RegisterAuthIdentityRequest
140
+ {
141
+ UserName = "admin",
142
+ Email = "admin@example.com",
143
+ Password = "Pass123$",
144
+ DisplayName = "Administrator",
145
+ DisplayCultureName = "it-IT",
146
+ CreateChillAuthUser = true
147
+ });
148
+ ```
149
+
150
+ After a successful registration, the client stores the returned access token and refresh token internally.
151
+
152
+ If `DisplayCultureName` is provided and `CreateChillAuthUser = true`, the linked `AuthUser` is initialized with culture-based defaults for:
153
+
154
+ - `DisplayTimeZone`
155
+ - `DisplayDateFormat`
156
+ - `DisplayNumberFormat`
157
+
158
+ For example, `it-IT` typically produces presets like:
159
+
160
+ - `DisplayTimeZone = "W. Europe Standard Time"`
161
+ - `DisplayDateFormat = "DD/MM/YYYY"`
162
+ - `DisplayNumberFormat = "1.000,00"`
163
+
164
+ These are server-side presets and can be edited later through auth-user management.
165
+
166
+ ## 6. Log in explicitly
167
+
168
+ If the account already exists, log in with the same `ChillSharpClient`.
169
+
170
+ ```csharp
171
+ var loginResponse = client.LoginAuthAccount(new LoginAuthIdentityRequest
172
+ {
173
+ UserNameOrEmail = "admin",
174
+ Password = "Pass123$"
175
+ });
176
+ ```
177
+
178
+ ## 7. Call protected endpoints
179
+
180
+ Once authenticated, the same client can call protected ChillSharp endpoints.
181
+
182
+ ```csharp
183
+ using ChillSharp.Client.Dto;
184
+
185
+ var query = new ChillDtoQuery
186
+ {
187
+ ChillType = "Query.BlogQuery"
188
+ };
189
+ query.ResultProperties = ChillDtoProperty.Build("Guid", "Name");
190
+
191
+ var result = client.Query(query);
192
+ Console.WriteLine(result.Results.Count);
193
+ ```
194
+
195
+ ## 8. Let the client refresh tokens automatically
196
+
197
+ You do not need to manually attach bearer tokens on every request. If the client already has a refresh token, authenticated calls renew the access token when needed.
198
+
199
+ ```csharp
200
+ var roles = client.GetAuthRoles();
201
+ ```
202
+
203
+ You can also refresh explicitly:
204
+
205
+ ```csharp
206
+ var refreshed = client.RefreshAuthAccount();
207
+ ```
208
+
209
+ ## Notes
210
+
211
+ - Use `options.ProtectedApi = true` on `AddChillApi<TContext>(...)` if your ChillSharp endpoints must require authentication.
212
+ - The root user created by `AddChillApi<TContext, TUser>(...)` is the bootstrap administrator path. When `CreateChillAuthUserForRoot = true`, the linked ChillSharp `AuthUser` is created with `CanManagePermissions = true`.
213
+ - `CreateChillAuthUser = true` creates the linked ChillSharp `AuthUser`, but it does not automatically grant admin permissions.
214
+ - `DisplayCultureName` on registration presets `DisplayTimeZone`, `DisplayDateFormat`, and `DisplayNumberFormat` for the linked `AuthUser`.
215
+ - For production, bootstrap the first administrator deliberately, for example through root-user initialization or a trusted install-time flow.
216
+
217
+ Next example: [Create a Docker image and configure it with environment variables](04-docker-env-variables.md)
218
+
@@ -0,0 +1,194 @@
1
+ # HOW-TO: Handle a One-to-Many Blog-Posts Relation
2
+
3
+ Versione italiana: [Italiano](../it/HowTo/04-blog-posts-one-to-many.md)
4
+
5
+ This example extends the blog model with posts and shows how to load one blog together with its posts in a single `ChillSharpClient.Query(...)` call.
6
+
7
+ ## Goal
8
+
9
+ Model a `Blog` to `Posts` one-to-many relation and project the nested collection from the ChillSharp client.
10
+
11
+ ## 1. Define the entities
12
+
13
+ ```csharp
14
+ using ChillSharp.Annotations;
15
+ using ChillSharp.EF;
16
+ using System.ComponentModel.DataAnnotations;
17
+
18
+ namespace MyBlogApp.Model;
19
+
20
+ [ChillEntity]
21
+ public class Blog : ChillEntity
22
+ {
23
+ [Key]
24
+ public override Guid Guid { get; set; }
25
+
26
+ [ChillProperty]
27
+ public string Name { get; set; } = string.Empty;
28
+
29
+ [ChillProperty]
30
+ public string? Url { get; set; }
31
+
32
+ [ChillProperty]
33
+ public ICollection<Post>? Posts { get; set; }
34
+
35
+ public override string GetLabel(IChillContext context) => Name;
36
+ }
37
+
38
+ [ChillEntity]
39
+ public class Post : ChillEntity
40
+ {
41
+ [Key]
42
+ public override Guid Guid { get; set; }
43
+
44
+ [ChillProperty]
45
+ public Blog? Blog { get; set; }
46
+
47
+ [ChillProperty]
48
+ public DateTime? CreatedAt { get; set; }
49
+
50
+ [ChillProperty]
51
+ public string Title { get; set; } = string.Empty;
52
+
53
+ [ChillProperty]
54
+ public string Content { get; set; } = string.Empty;
55
+
56
+ public override void OnCreate(IChillContext context)
57
+ {
58
+ base.OnCreate(context);
59
+ CreatedAt = DateTime.UtcNow;
60
+ }
61
+
62
+ public override string GetLabel(IChillContext context) => Title;
63
+ }
64
+ ```
65
+
66
+ ## 2. Add both sets to the context
67
+
68
+ ```csharp
69
+ using Microsoft.EntityFrameworkCore;
70
+ using MyBlogApp.Model;
71
+
72
+ namespace MyBlogApp;
73
+
74
+ public class BloggingContext : DbContext, IChillContext
75
+ {
76
+ public DbSet<Blog> Blogs => Set<Blog>();
77
+ public DbSet<Post> Posts => Set<Post>();
78
+
79
+ public BloggingContext(DbContextOptions<BloggingContext> options) : base(options)
80
+ {
81
+ }
82
+
83
+ public string GetChillTypePrefix() => "MyBlogApp";
84
+ }
85
+ ```
86
+
87
+ ## 3. Define a query for blogs
88
+
89
+ ```csharp
90
+ using ChillSharp.Annotations;
91
+ using ChillSharp.EF;
92
+
93
+ namespace MyBlogApp.Query;
94
+
95
+ [ChillEntity]
96
+ public class BlogQuery : ChillQuery
97
+ {
98
+ [ChillProperty]
99
+ public string? Name { get; set; }
100
+
101
+ public override IQueryable<IChillEntity> OnQuery(IChillContext context)
102
+ {
103
+ var db = (BloggingContext)context;
104
+ var query = db.Blogs.AsQueryable();
105
+
106
+ if (Guid.HasValue)
107
+ query = query.Where(x => x.Guid == Guid.Value);
108
+
109
+ if (!string.IsNullOrWhiteSpace(Name))
110
+ query = query.Where(x => x.Name.Contains(Name));
111
+
112
+ return query;
113
+ }
114
+ }
115
+ ```
116
+
117
+ ## 4. Create a blog and two posts
118
+
119
+ The relation is created by sending the parent `Blog` DTO as the `Blog` property of each `Post`.
120
+
121
+ ```csharp
122
+ using ChillSharp.Client;
123
+ using ChillSharp.Client.Dto;
124
+
125
+ var client = new ChillSharpClient("http://localhost:5000/api/chill");
126
+
127
+ var blog = new ChillDtoEntity
128
+ {
129
+ ChillType = "Model.Blog",
130
+ Guid = Guid.NewGuid()
131
+ };
132
+ blog.Properties["Name"] = "ChillSharp Blog";
133
+ blog.Properties["Url"] = "https://example.local/chillsharp-blog";
134
+
135
+ var createdBlog = client.Create(blog);
136
+
137
+ var firstPost = new ChillDtoEntity
138
+ {
139
+ ChillType = "Model.Post",
140
+ Guid = Guid.NewGuid()
141
+ };
142
+ firstPost.Properties["Title"] = "First post";
143
+ firstPost.Properties["Content"] = "Hello from ChillSharp";
144
+ firstPost.Properties["Blog"] = createdBlog.Mock();
145
+ client.Create(firstPost);
146
+
147
+ var secondPost = new ChillDtoEntity
148
+ {
149
+ ChillType = "Model.Post",
150
+ Guid = Guid.NewGuid()
151
+ };
152
+ secondPost.Properties["Title"] = "Second post";
153
+ secondPost.Properties["Content"] = "Nested queries are handy";
154
+ secondPost.Properties["Blog"] = createdBlog.Mock();
155
+ client.Create(secondPost);
156
+ ```
157
+
158
+ ## 5. Load one blog with its posts in one call
159
+
160
+ This is the part that matters most for a one-to-many relation: the nested projection is described through `ChillDtoProperty.With(...)`, and the returned collection is read with `GetCollection(...)`.
161
+
162
+ ```csharp
163
+ using ChillSharp.Client.Dto;
164
+
165
+ var query = new ChillDtoQuery
166
+ {
167
+ ChillType = "Query.BlogQuery"
168
+ };
169
+ query.Properties["Guid"] = createdBlog.Guid;
170
+ query.ResultProperties = ChillDtoProperty.Build(
171
+ "Guid",
172
+ "Name",
173
+ "Url",
174
+ ChillDtoProperty.With("Posts", "Guid", "Title", "CreatedAt"));
175
+
176
+ var queryResult = client.Query(query);
177
+ var loadedBlog = queryResult.Results.Single();
178
+
179
+ Console.WriteLine(loadedBlog.GetString("Name"));
180
+
181
+ foreach (var post in loadedBlog.GetCollection("Posts"))
182
+ {
183
+ Console.WriteLine(post.GetString("Title"));
184
+ }
185
+ ```
186
+
187
+ ## What this gives you
188
+
189
+ - one HTTP call to load the parent entity and the child collection
190
+ - a strongly-typed projection builder on the client side
191
+ - DTO-based relation handling without writing a dedicated controller for `Blog` or `Post`
192
+
193
+ Next: [Back to the documentation index](../README.md)
194
+