@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.
- package/.agents/skills/chillsharp-current-user-preferences/SKILL.md +70 -0
- package/.agents/skills/chillsharp-ui-template/SKILL.md +18 -0
- package/README.md +103 -0
- package/chill-sharp-ui-core.d.ts.map +1 -0
- package/doc/AIAssistedDevelopment/README.md +185 -0
- package/doc/AttachmentModel/README.md +173 -0
- package/doc/AuthenticationModel/README.md +213 -0
- package/doc/AuthenticationModel/how-to-integreate-auth-minimal-api.md +293 -0
- package/doc/ChillSharpClient.md +464 -0
- package/doc/ClientGeneration/README.md +172 -0
- package/doc/ComplianceGuide/README.md +178 -0
- package/doc/Configuration/README.md +94 -0
- package/doc/CurrentUserPreferences.md +114 -0
- package/doc/DateTimePolicy/README.md +154 -0
- package/doc/DateTimeSerialization.md +423 -0
- package/doc/Endpoints.md +260 -0
- package/doc/HowTo/01-simple-blog-sqlite.md +153 -0
- package/doc/HowTo/02-blog-schema-labels.md +140 -0
- package/doc/HowTo/03-authentication.md +218 -0
- package/doc/HowTo/04-blog-posts-one-to-many.md +194 -0
- package/doc/HowTo/05-docker-env-variables.md +274 -0
- package/doc/HowTo/06-chunk-transactions-autocomplete.md +196 -0
- package/doc/Mcp/ChatGPT.md +291 -0
- package/doc/Mcp/README.md +799 -0
- package/doc/MenuGuide/README.md +49 -0
- package/doc/ModelPreparation.md +255 -0
- package/doc/PermissionModel/README.md +277 -0
- package/doc/README.md +228 -0
- package/doc/ReferenceExistence.md +130 -0
- package/doc/RegisterContext.md +217 -0
- package/doc/UiCore/CRUD.md +170 -0
- package/doc/UiCore/README.md +13 -0
- package/doc/ValidationModel/README.md +117 -0
- package/doc/it/AIAssistedDevelopment/README.md +185 -0
- package/doc/it/AttachmentModel/README.md +173 -0
- package/doc/it/AuthenticationModel/README.md +171 -0
- package/doc/it/AuthenticationModel/how-to-integreate-auth-minimal-api.md +292 -0
- package/doc/it/ChillSharpClient.md +464 -0
- package/doc/it/ClientGeneration/README.md +152 -0
- package/doc/it/ComplianceGuide/README.md +178 -0
- package/doc/it/Configuration/README.md +94 -0
- package/doc/it/CurrentUserPreferences.md +114 -0
- package/doc/it/DateTimePolicy/README.md +154 -0
- package/doc/it/DateTimeSerialization.md +423 -0
- package/doc/it/Endpoints.md +260 -0
- package/doc/it/HowTo/01-simple-blog-sqlite.md +152 -0
- package/doc/it/HowTo/02-blog-schema-labels.md +139 -0
- package/doc/it/HowTo/03-authentication.md +221 -0
- package/doc/it/HowTo/04-blog-posts-one-to-many.md +193 -0
- package/doc/it/HowTo/05-docker-env-variables.md +268 -0
- package/doc/it/HowTo/06-chunk-transactions-autocomplete.md +196 -0
- package/doc/it/Mcp/ChatGPT.md +291 -0
- package/doc/it/Mcp/README.md +799 -0
- package/doc/it/MenuGuide/README.md +49 -0
- package/doc/it/ModelPreparation.md +254 -0
- package/doc/it/PermissionModel/README.md +190 -0
- package/doc/it/README.md +172 -0
- package/doc/it/ReferenceExistence.md +130 -0
- package/doc/it/RegisterContext.md +218 -0
- package/doc/it/UiCore/CRUD.md +170 -0
- package/doc/it/UiCore/README.md +13 -0
- package/doc/it/ValidationModel/README.md +117 -0
- package/fesm2022/chill-sharp-ui-core.mjs +16725 -0
- package/fesm2022/chill-sharp-ui-core.mjs.map +1 -0
- package/index.d.ts +6 -0
- package/lib/chill-sharp-ui-root.component.d.ts +6 -0
- package/lib/chill-sharp-ui-root.component.d.ts.map +1 -0
- package/lib/chill-sharp-ui.routes.d.ts +3 -0
- package/lib/chill-sharp-ui.routes.d.ts.map +1 -0
- package/lib/chill.config.d.ts +5 -0
- package/lib/chill.config.d.ts.map +1 -0
- package/lib/layouts/auth-shell.component.d.ts +8 -0
- package/lib/layouts/auth-shell.component.d.ts.map +1 -0
- package/lib/layouts/workspace-page.component.d.ts +49 -0
- package/lib/layouts/workspace-page.component.d.ts.map +1 -0
- package/lib/lib/chill-form.component.d.ts +151 -0
- package/lib/lib/chill-form.component.d.ts.map +1 -0
- package/lib/lib/chill-i18n-button-label.component.d.ts +27 -0
- package/lib/lib/chill-i18n-button-label.component.d.ts.map +1 -0
- package/lib/lib/chill-i18n-label.component.d.ts +30 -0
- package/lib/lib/chill-i18n-label.component.d.ts.map +1 -0
- package/lib/lib/chill-json-input.component.d.ts +31 -0
- package/lib/lib/chill-json-input.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-boolean-control.component.d.ts +12 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-boolean-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-editor-control.component.d.ts +17 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-editor-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-lookup-control.component.d.ts +45 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-lookup-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-scalar-control.component.d.ts +19 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-scalar-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-select-control.component.d.ts +12 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-select-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-textarea-control.component.d.ts +13 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-textarea-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input.component.d.ts +452 -0
- package/lib/lib/chill-polymorphic-input.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-boolean-control.component.d.ts +7 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-boolean-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-lookup-control.component.d.ts +7 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-lookup-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-number-control.component.d.ts +7 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-number-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-temporal-control.component.d.ts +8 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-temporal-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-value-control.component.d.ts +7 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-value-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output.component.d.ts +75 -0
- package/lib/lib/chill-polymorphic-output.component.d.ts.map +1 -0
- package/lib/lib/chill-table.component.d.ts +434 -0
- package/lib/lib/chill-table.component.d.ts.map +1 -0
- package/lib/lib/chill-text-editor-dialog.component.d.ts +14 -0
- package/lib/lib/chill-text-editor-dialog.component.d.ts.map +1 -0
- package/lib/lib/crud-configuration.utils.d.ts +4 -0
- package/lib/lib/crud-configuration.utils.d.ts.map +1 -0
- package/lib/lib/culture-name-options.d.ts +3 -0
- package/lib/lib/culture-name-options.d.ts.map +1 -0
- package/lib/lib/date-format-options.d.ts +3 -0
- package/lib/lib/date-format-options.d.ts.map +1 -0
- package/lib/lib/iana-time-zone-options.d.ts +3 -0
- package/lib/lib/iana-time-zone-options.d.ts.map +1 -0
- package/lib/lib/notice-transition.directive.d.ts +17 -0
- package/lib/lib/notice-transition.directive.d.ts.map +1 -0
- package/lib/lib/schema-property-dialog.component.d.ts +74 -0
- package/lib/lib/schema-property-dialog.component.d.ts.map +1 -0
- package/lib/models/chill-auth.models.d.ts +176 -0
- package/lib/models/chill-auth.models.d.ts.map +1 -0
- package/lib/models/chill-menu.models.d.ts +12 -0
- package/lib/models/chill-menu.models.d.ts.map +1 -0
- package/lib/models/chill-schema.models.d.ts +141 -0
- package/lib/models/chill-schema.models.d.ts.map +1 -0
- package/lib/models/workspace-dialog.models.d.ts +16 -0
- package/lib/models/workspace-dialog.models.d.ts.map +1 -0
- package/lib/models/workspace-task.models.d.ts +36 -0
- package/lib/models/workspace-task.models.d.ts.map +1 -0
- package/lib/pages/confirm-reset-page.component.d.ts +21 -0
- package/lib/pages/confirm-reset-page.component.d.ts.map +1 -0
- package/lib/pages/crud/attachment-upload-dialog.component.d.ts +24 -0
- package/lib/pages/crud/attachment-upload-dialog.component.d.ts.map +1 -0
- package/lib/pages/crud/crud-page.component.d.ts +244 -0
- package/lib/pages/crud/crud-page.component.d.ts.map +1 -0
- package/lib/pages/login-page.component.d.ts +21 -0
- package/lib/pages/login-page.component.d.ts.map +1 -0
- package/lib/pages/permissions/auth-role-dialog.component.d.ts +29 -0
- package/lib/pages/permissions/auth-role-dialog.component.d.ts.map +1 -0
- package/lib/pages/permissions/auth-search-select.component.d.ts +28 -0
- package/lib/pages/permissions/auth-search-select.component.d.ts.map +1 -0
- package/lib/pages/permissions/auth-user-dialog.component.d.ts +35 -0
- package/lib/pages/permissions/auth-user-dialog.component.d.ts.map +1 -0
- package/lib/pages/permissions/permission-editor.component.d.ts +55 -0
- package/lib/pages/permissions/permission-editor.component.d.ts.map +1 -0
- package/lib/pages/permissions/permissions-page.component.d.ts +38 -0
- package/lib/pages/permissions/permissions-page.component.d.ts.map +1 -0
- package/lib/pages/permissions/role-permission.component.d.ts +43 -0
- package/lib/pages/permissions/role-permission.component.d.ts.map +1 -0
- package/lib/pages/permissions/user-permission.component.d.ts +43 -0
- package/lib/pages/permissions/user-permission.component.d.ts.map +1 -0
- package/lib/pages/register-page.component.d.ts +24 -0
- package/lib/pages/register-page.component.d.ts.map +1 -0
- package/lib/pages/reset-password-page.component.d.ts +18 -0
- package/lib/pages/reset-password-page.component.d.ts.map +1 -0
- package/lib/provide-chill-sharp-ui-core.d.ts +8 -0
- package/lib/provide-chill-sharp-ui-core.d.ts.map +1 -0
- package/lib/services/chill.service.d.ts +249 -0
- package/lib/services/chill.service.d.ts.map +1 -0
- package/lib/services/workspace-dialog.service.d.ts +22 -0
- package/lib/services/workspace-dialog.service.d.ts.map +1 -0
- package/lib/services/workspace-layout.service.d.ts +13 -0
- package/lib/services/workspace-layout.service.d.ts.map +1 -0
- package/lib/services/workspace-task-registry.service.d.ts +35 -0
- package/lib/services/workspace-task-registry.service.d.ts.map +1 -0
- package/lib/services/workspace-toolbar.service.d.ts +23 -0
- package/lib/services/workspace-toolbar.service.d.ts.map +1 -0
- package/lib/services/workspace.service.d.ts +114 -0
- package/lib/services/workspace.service.d.ts.map +1 -0
- package/lib/storage-keys.d.ts +5 -0
- package/lib/storage-keys.d.ts.map +1 -0
- package/lib/tasks/crud-task/crud-task.component.d.ts +33 -0
- package/lib/tasks/crud-task/crud-task.component.d.ts.map +1 -0
- package/lib/tasks/goto-url-task/goto-url-task.component.d.ts +31 -0
- package/lib/tasks/goto-url-task/goto-url-task.component.d.ts.map +1 -0
- package/lib/workspace/confirm-message-dialog.component.d.ts +16 -0
- package/lib/workspace/confirm-message-dialog.component.d.ts.map +1 -0
- package/lib/workspace/entity-options-dialog.component.d.ts +29 -0
- package/lib/workspace/entity-options-dialog.component.d.ts.map +1 -0
- package/lib/workspace/external-task-api.d.ts +2 -0
- package/lib/workspace/external-task-api.d.ts.map +1 -0
- package/lib/workspace/user-profile-dialog.component.d.ts +30 -0
- package/lib/workspace/user-profile-dialog.component.d.ts.map +1 -0
- package/lib/workspace/workspace-dialog-host.component.d.ts +26 -0
- package/lib/workspace/workspace-dialog-host.component.d.ts.map +1 -0
- package/lib/workspace/workspace-menu-item-dialog.component.d.ts +61 -0
- package/lib/workspace/workspace-menu-item-dialog.component.d.ts.map +1 -0
- package/lib/workspace/workspace-menu.component.d.ts +104 -0
- package/lib/workspace/workspace-menu.component.d.ts.map +1 -0
- package/lib/workspace/workspace-taskbar.component.d.ts +14 -0
- package/lib/workspace/workspace-taskbar.component.d.ts.map +1 -0
- package/package.json +54 -0
- package/public-api.d.ts +56 -0
- package/public-api.d.ts.map +1 -0
- package/service-worker/chill-sharp-service-worker.js +166 -0
- package/styles/core-theme.scss +1268 -0
- package/template-customization/upgrade.ps1.template +342 -0
- package/template-customization/upgrade.sh.template +271 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# HOW-TO: Create a Docker Image and Configure It with Environment Variables
|
|
2
|
+
|
|
3
|
+
Versione italiana: [Italiano](../it/HowTo/05-docker-env-variables.md)
|
|
4
|
+
|
|
5
|
+
This example shows how to package a ChillSharp API into a Docker image and configure it at runtime through environment variables instead of hardcoded values.
|
|
6
|
+
|
|
7
|
+
## Goal
|
|
8
|
+
|
|
9
|
+
Build one container image that can be reused across environments by changing only environment variables.
|
|
10
|
+
|
|
11
|
+
## 1. Read configuration from environment-aware `IConfiguration`
|
|
12
|
+
|
|
13
|
+
ASP.NET Core already maps environment variables into `builder.Configuration`. Use that instead of hardcoding the SQLite path, module toggles, token lifetimes, SMTP settings, or root-user credentials.
|
|
14
|
+
|
|
15
|
+
For the DTO date/time mapper, ChillSharp also reads `CHILLSHARP_SYSTEM_TIMEZONE` directly from the process environment. It should be an IANA id such as `Europe/Rome`.
|
|
16
|
+
|
|
17
|
+
This setting is used for ChillSharp `DateTime` handling and for UTC-to-local normalization of some `DateTimeOffset` inputs. `DateOnly` and `TimeOnly` keep normal .NET string output.
|
|
18
|
+
|
|
19
|
+
`ChillSharp.Attachment` also reads `CHILLSHARP_ATTACHMENT_ARCHIVE_ROOT` directly. In containers, point it at a mounted volume such as `/attachments`.
|
|
20
|
+
|
|
21
|
+
```csharp
|
|
22
|
+
using ChillSharp.Api;
|
|
23
|
+
using ChillSharp.Auth;
|
|
24
|
+
using ChillSharp.Auth.Api;
|
|
25
|
+
using ChillSharp.Attachment.Services;
|
|
26
|
+
using Microsoft.AspNetCore.Identity;
|
|
27
|
+
using Microsoft.EntityFrameworkCore;
|
|
28
|
+
|
|
29
|
+
var builder = WebApplication.CreateBuilder(args);
|
|
30
|
+
|
|
31
|
+
var databasePath = builder.Configuration["CHILLSHARP_DB_PATH"] ?? "/data/blogging.db";
|
|
32
|
+
var attachmentArchiveRoot = builder.Configuration["CHILLSHARP_ATTACHMENT_ARCHIVE_ROOT"] ?? "/attachments";
|
|
33
|
+
|
|
34
|
+
builder.Services.AddDbContext<BloggingContext>(options =>
|
|
35
|
+
options.UseSqlite($"Data Source={databasePath}"));
|
|
36
|
+
|
|
37
|
+
builder.Services.AddIdentityCore<IdentityUser>()
|
|
38
|
+
.AddEntityFrameworkStores<BloggingContext>()
|
|
39
|
+
.AddSignInManager()
|
|
40
|
+
.AddDefaultTokenProviders();
|
|
41
|
+
|
|
42
|
+
builder.Services.AddAuthentication(ChillAuthIdentityDefaults.AuthenticationScheme)
|
|
43
|
+
.AddChillAuthBearer();
|
|
44
|
+
|
|
45
|
+
builder.Services.AddAuthorization();
|
|
46
|
+
|
|
47
|
+
builder.Services.AddChillApi<BloggingContext>(options =>
|
|
48
|
+
{
|
|
49
|
+
options.ProtectedApi = GetBool("CHILLSHARP_API_PROTECTED", true);
|
|
50
|
+
options.ApiBasePath = builder.Configuration["CHILLSHARP_API_BASE_PATH"] ?? "/api";
|
|
51
|
+
options.EnableSchemaApi = GetBool("CHILLSHARP_ENABLE_SCHEMA", true);
|
|
52
|
+
options.EnableAuthApi = GetBool("CHILLSHARP_ENABLE_AUTH", true);
|
|
53
|
+
options.EnableI18nApi = GetBool("CHILLSHARP_ENABLE_I18N", true);
|
|
54
|
+
options.EnableMcpApi = GetBool("CHILLSHARP_ENABLE_MCP", true);
|
|
55
|
+
options.EnableAttachmentApi = GetBool("CHILLSHARP_ENABLE_ATTACHMENT", false);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
builder.Services.AddChillAuthIdentityApi<BloggingContext, IdentityUser>(options =>
|
|
59
|
+
{
|
|
60
|
+
// ChillSharp reads these two environment variables as defaults:
|
|
61
|
+
// CHILLSHARP_AUTH_ACCESS_TOKEN_MINUTES and CHILLSHARP_AUTH_REFRESH_TOKEN_DAYS.
|
|
62
|
+
// Set them here only when you want this host startup code to control the mapping explicitly.
|
|
63
|
+
options.AccessTokenLifetime = TimeSpan.FromMinutes(GetInt("CHILLSHARP_AUTH_ACCESS_TOKEN_MINUTES", 20));
|
|
64
|
+
options.RefreshTokenLifetime = TimeSpan.FromDays(GetInt("CHILLSHARP_AUTH_REFRESH_TOKEN_DAYS", 14));
|
|
65
|
+
options.ReturnPasswordResetTokensInResponse = GetBool("CHILLSHARP_AUTH_RETURN_PASSWORD_RESET_TOKENS", false);
|
|
66
|
+
options.SendPasswordResetEmails = GetBool("CHILLSHARP_AUTH_SEND_PASSWORD_RESET_EMAILS", true);
|
|
67
|
+
options.InitializeRootUserOnStartup = GetBool("CHILLSHARP_AUTH_INITIALIZE_ROOT_USER", true);
|
|
68
|
+
options.CreateChillAuthUserForRoot = GetBool("CHILLSHARP_AUTH_CREATE_ROOT_AUTH_USER", true);
|
|
69
|
+
options.PasswordResetEmailSubject = builder.Configuration["CHILLSHARP_AUTH_PASSWORD_RESET_SUBJECT"] ?? "Reset your password";
|
|
70
|
+
options.PasswordResetUrlBase = builder.Configuration["CHILLSHARP_AUTH_PASSWORD_RESET_URL"];
|
|
71
|
+
options.SmtpHost = builder.Configuration["CHILLSHARP_SMTP_HOST"];
|
|
72
|
+
options.SmtpPort = GetInt("CHILLSHARP_SMTP_PORT", 587);
|
|
73
|
+
options.SmtpEnableSsl = GetBool("CHILLSHARP_SMTP_ENABLE_SSL", true);
|
|
74
|
+
options.SmtpUserName = builder.Configuration["CHILLSHARP_SMTP_USERNAME"];
|
|
75
|
+
options.SmtpPassword = builder.Configuration["CHILLSHARP_SMTP_PASSWORD"];
|
|
76
|
+
options.PasswordResetFromEmail = builder.Configuration["CHILLSHARP_SMTP_FROM_EMAIL"];
|
|
77
|
+
options.PasswordResetFromDisplayName = builder.Configuration["CHILLSHARP_SMTP_FROM_DISPLAY_NAME"];
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
builder.Services.Configure<ChillAttachmentOptions>(options =>
|
|
81
|
+
{
|
|
82
|
+
options.ArchiveRoot = attachmentArchiveRoot;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
var app = builder.Build();
|
|
86
|
+
|
|
87
|
+
app.UseAuthentication();
|
|
88
|
+
app.UseAuthorization();
|
|
89
|
+
|
|
90
|
+
Directory.CreateDirectory(Path.GetDirectoryName(databasePath)!);
|
|
91
|
+
Directory.CreateDirectory(attachmentArchiveRoot);
|
|
92
|
+
|
|
93
|
+
using (var scope = app.Services.CreateScope())
|
|
94
|
+
{
|
|
95
|
+
var db = scope.ServiceProvider.GetRequiredService<BloggingContext>();
|
|
96
|
+
db.Database.EnsureCreated();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
app.MapChillApi();
|
|
100
|
+
app.Run();
|
|
101
|
+
|
|
102
|
+
bool GetBool(string name, bool defaultValue)
|
|
103
|
+
{
|
|
104
|
+
return bool.TryParse(builder.Configuration[name], out var value) ? value : defaultValue;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
int GetInt(string name, int defaultValue)
|
|
108
|
+
{
|
|
109
|
+
return int.TryParse(builder.Configuration[name], out var value) ? value : defaultValue;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The MCP and attachment modules are registered by `AddChillApi<TContext>()` only when the `DbContext` implements their required interfaces:
|
|
114
|
+
|
|
115
|
+
- `ChillSharp.Schema` and `ChillSharp.Mcp`: `IChillSchemaDbContext`
|
|
116
|
+
- `ChillSharp.Auth`: `IChillAuthDbContext`
|
|
117
|
+
- `ChillSharp.I18n`: `IChillI18nDbContext`
|
|
118
|
+
- `ChillSharp.Attachment`: `IChillAttachmentDbContext`
|
|
119
|
+
|
|
120
|
+
Keep `CHILLSHARP_ENABLE_ATTACHMENT=false` until your context exposes the attachment model and archive storage. Then switch it to `true` and keep `/attachments` mounted.
|
|
121
|
+
|
|
122
|
+
## 2. Use environment variables for modules and runtime settings
|
|
123
|
+
|
|
124
|
+
These names are a good container baseline for the current built-in modules:
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
CHILLSHARP_DB_PATH
|
|
128
|
+
CHILLSHARP_SYSTEM_TIMEZONE
|
|
129
|
+
CHILLSHARP_API_PROTECTED
|
|
130
|
+
CHILLSHARP_API_BASE_PATH
|
|
131
|
+
CHILLSHARP_ENABLE_SCHEMA
|
|
132
|
+
CHILLSHARP_ENABLE_AUTH
|
|
133
|
+
CHILLSHARP_ENABLE_I18N
|
|
134
|
+
CHILLSHARP_ENABLE_MCP
|
|
135
|
+
CHILLSHARP_ENABLE_ATTACHMENT
|
|
136
|
+
CHILLSHARP_ATTACHMENT_ARCHIVE_ROOT
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`CHILLSHARP_ENABLE_*` variables are example-host variables: your app reads them from `IConfiguration` and maps them to `ChillApiOptions`. `CHILLSHARP_API_BASE_PATH` defaults to `/api` and is also read by ChillSharp when you do not set `ChillApiOptions.ApiBasePath` explicitly. `CHILLSHARP_SYSTEM_TIMEZONE`, `CHILLSHARP_ATTACHMENT_ARCHIVE_ROOT`, and the root-user variables below are read directly by ChillSharp services too.
|
|
140
|
+
|
|
141
|
+
When enabled, the default endpoints include:
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
http://localhost:8080/api/chill
|
|
145
|
+
http://localhost:8080/api/chill-auth
|
|
146
|
+
http://localhost:8080/api/chill-attachment
|
|
147
|
+
http://localhost:8080/api/chill-mcp
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## 3. Use environment variables for the root user
|
|
151
|
+
|
|
152
|
+
`AddChillAuthIdentityApi(...)` already knows these variables:
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
CHILLSHARP_AUTH_ROOT_USERNAME
|
|
156
|
+
CHILLSHARP_AUTH_ROOT_PASSWORD
|
|
157
|
+
CHILLSHARP_AUTH_ROOT_EMAIL
|
|
158
|
+
CHILLSHARP_AUTH_ROOT_DISPLAY_NAME
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
When `CreateChillAuthUserForRoot = true`, the root `AuthUser` is also created with `CanManagePermissions = true`.
|
|
162
|
+
|
|
163
|
+
## 4. Create the Dockerfile
|
|
164
|
+
|
|
165
|
+
This image builds the application once and runs it with the ASP.NET Core runtime image.
|
|
166
|
+
|
|
167
|
+
```dockerfile
|
|
168
|
+
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
|
169
|
+
WORKDIR /src
|
|
170
|
+
|
|
171
|
+
COPY MyBlogApp.csproj ./
|
|
172
|
+
RUN dotnet restore
|
|
173
|
+
|
|
174
|
+
COPY . ./
|
|
175
|
+
RUN dotnet publish -c Release -o /app/out
|
|
176
|
+
|
|
177
|
+
FROM mcr.microsoft.com/dotnet/aspnet:8.0
|
|
178
|
+
WORKDIR /app
|
|
179
|
+
|
|
180
|
+
COPY --from=build /app/out ./
|
|
181
|
+
|
|
182
|
+
ENV ASPNETCORE_URLS=http://+:8080
|
|
183
|
+
ENV CHILLSHARP_DB_PATH=/data/blogging.db
|
|
184
|
+
ENV CHILLSHARP_SYSTEM_TIMEZONE=Europe/Rome
|
|
185
|
+
ENV CHILLSHARP_ATTACHMENT_ARCHIVE_ROOT=/attachments
|
|
186
|
+
|
|
187
|
+
VOLUME ["/data"]
|
|
188
|
+
VOLUME ["/attachments"]
|
|
189
|
+
EXPOSE 8080
|
|
190
|
+
|
|
191
|
+
ENTRYPOINT ["dotnet", "MyBlogApp.dll"]
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## 5. Build the image
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
docker build -t myblogapp:latest .
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## 6. Run the container with environment variables
|
|
201
|
+
|
|
202
|
+
This example starts the API, persists SQLite data and attachment files in local Docker volumes, and creates the root administrator at startup.
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
docker run --rm -p 8080:8080 \
|
|
206
|
+
-v myblogapp-data:/data \
|
|
207
|
+
-v myblogapp-attachments:/attachments \
|
|
208
|
+
-e CHILLSHARP_DB_PATH=/data/blogging.db \
|
|
209
|
+
-e CHILLSHARP_SYSTEM_TIMEZONE=Europe/Rome \
|
|
210
|
+
-e CHILLSHARP_API_PROTECTED=true \
|
|
211
|
+
-e CHILLSHARP_ENABLE_SCHEMA=true \
|
|
212
|
+
-e CHILLSHARP_ENABLE_AUTH=true \
|
|
213
|
+
-e CHILLSHARP_ENABLE_I18N=true \
|
|
214
|
+
-e CHILLSHARP_ENABLE_MCP=true \
|
|
215
|
+
-e CHILLSHARP_ENABLE_ATTACHMENT=false \
|
|
216
|
+
-e CHILLSHARP_ATTACHMENT_ARCHIVE_ROOT=/attachments \
|
|
217
|
+
-e CHILLSHARP_AUTH_ROOT_USERNAME=root \
|
|
218
|
+
-e CHILLSHARP_AUTH_ROOT_PASSWORD=Pass123$ \
|
|
219
|
+
-e CHILLSHARP_AUTH_ROOT_EMAIL=root@example.com \
|
|
220
|
+
-e CHILLSHARP_AUTH_ROOT_DISPLAY_NAME="Root Administrator" \
|
|
221
|
+
myblogapp:latest
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
With the values above, the application is then available at:
|
|
225
|
+
|
|
226
|
+
```text
|
|
227
|
+
http://localhost:8080/api/chill
|
|
228
|
+
http://localhost:8080/api/chill-auth
|
|
229
|
+
http://localhost:8080/api/chill-mcp
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Set `CHILLSHARP_ENABLE_ATTACHMENT=true` when the host context implements `IChillAttachmentDbContext`; then the attachment API is available at `http://localhost:8080/api/chill-attachment`.
|
|
233
|
+
|
|
234
|
+
## 7. Optional `docker compose` example
|
|
235
|
+
|
|
236
|
+
```yaml
|
|
237
|
+
services:
|
|
238
|
+
myblogapp:
|
|
239
|
+
image: myblogapp:latest
|
|
240
|
+
build: .
|
|
241
|
+
ports:
|
|
242
|
+
- "8080:8080"
|
|
243
|
+
environment:
|
|
244
|
+
ASPNETCORE_URLS: http://+:8080
|
|
245
|
+
CHILLSHARP_DB_PATH: /data/blogging.db
|
|
246
|
+
CHILLSHARP_SYSTEM_TIMEZONE: Europe/Rome
|
|
247
|
+
CHILLSHARP_API_PROTECTED: "true"
|
|
248
|
+
CHILLSHARP_API_BASE_PATH: /api
|
|
249
|
+
CHILLSHARP_ENABLE_SCHEMA: "true"
|
|
250
|
+
CHILLSHARP_ENABLE_AUTH: "true"
|
|
251
|
+
CHILLSHARP_ENABLE_I18N: "true"
|
|
252
|
+
CHILLSHARP_ENABLE_MCP: "true"
|
|
253
|
+
CHILLSHARP_ENABLE_ATTACHMENT: "false"
|
|
254
|
+
CHILLSHARP_ATTACHMENT_ARCHIVE_ROOT: /attachments
|
|
255
|
+
CHILLSHARP_AUTH_ROOT_USERNAME: root
|
|
256
|
+
CHILLSHARP_AUTH_ROOT_PASSWORD: Pass123$
|
|
257
|
+
CHILLSHARP_AUTH_ROOT_EMAIL: root@example.com
|
|
258
|
+
CHILLSHARP_AUTH_ROOT_DISPLAY_NAME: Root Administrator
|
|
259
|
+
volumes:
|
|
260
|
+
- myblogapp-data:/data
|
|
261
|
+
- myblogapp-attachments:/attachments
|
|
262
|
+
|
|
263
|
+
volumes:
|
|
264
|
+
myblogapp-data:
|
|
265
|
+
myblogapp-attachments:
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Notes
|
|
269
|
+
|
|
270
|
+
- Keep the image generic and push environment-specific values into runtime configuration.
|
|
271
|
+
- Persist SQLite under a mounted volume, otherwise the database is lost when the container is removed.
|
|
272
|
+
- For production, inject secrets through your container platform or secret manager instead of hardcoding them in `docker run` history or `compose` files.
|
|
273
|
+
|
|
274
|
+
Next example: [Handle a one-to-many Blog-Posts relation and fetch it in one client call](05-blog-posts-one-to-many.md)
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# HOW-TO: Use Chunk, Transactions, and Autocomplete
|
|
2
|
+
|
|
3
|
+
Versione italiana: [Italiano](../it/HowTo/06-chunk-transactions-autocomplete.md)
|
|
4
|
+
|
|
5
|
+
This example shows how to send multiple ChillSharp operations in one call with `chunk`, how to wrap write operations in one database transaction, and how to use `autocomplete` for entity and query DTOs.
|
|
6
|
+
|
|
7
|
+
## Goal
|
|
8
|
+
|
|
9
|
+
Use the core ChillSharp API efficiently when the client must:
|
|
10
|
+
|
|
11
|
+
- execute several operations in one HTTP request
|
|
12
|
+
- commit a group of writes atomically
|
|
13
|
+
- ask the server to complete or normalize DTO values before saving
|
|
14
|
+
|
|
15
|
+
## 1. Prepare the client
|
|
16
|
+
|
|
17
|
+
All examples below use the .NET client and assume the core API is mapped at `/api/chill`.
|
|
18
|
+
|
|
19
|
+
```csharp
|
|
20
|
+
using ChillSharp.Client;
|
|
21
|
+
using ChillSharp.Client.Dto;
|
|
22
|
+
|
|
23
|
+
var client = new ChillSharpClient("http://localhost:5000/api/chill");
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 2. Send multiple operations with `chunk`
|
|
27
|
+
|
|
28
|
+
`chunk` sends a list of `ChillOperation` items to `/api/chill/chunk`.
|
|
29
|
+
Each operation can contain a `Query` or an `Entity`, depending on the `Verb`.
|
|
30
|
+
|
|
31
|
+
Set `Index` explicitly when execution order matters.
|
|
32
|
+
|
|
33
|
+
```csharp
|
|
34
|
+
using ChillSharp.Client.Dto;
|
|
35
|
+
|
|
36
|
+
var firstPost = new ChillDtoEntity
|
|
37
|
+
{
|
|
38
|
+
ChillType = "Model.Post",
|
|
39
|
+
Guid = Guid.Parse("11111111-1111-1111-1111-111111111111")
|
|
40
|
+
};
|
|
41
|
+
firstPost.Properties["Title"] = "First";
|
|
42
|
+
firstPost.Properties["Author"] = "Ada";
|
|
43
|
+
|
|
44
|
+
var secondPost = new ChillDtoEntity
|
|
45
|
+
{
|
|
46
|
+
ChillType = "Model.Post",
|
|
47
|
+
Guid = Guid.Parse("22222222-2222-2222-2222-222222222222")
|
|
48
|
+
};
|
|
49
|
+
secondPost.Properties["Title"] = "Second";
|
|
50
|
+
secondPost.Properties["Author"] = "Linus";
|
|
51
|
+
|
|
52
|
+
var updateFirstPost = new ChillDtoEntity
|
|
53
|
+
{
|
|
54
|
+
ChillType = "Model.Post",
|
|
55
|
+
Guid = firstPost.Guid
|
|
56
|
+
};
|
|
57
|
+
updateFirstPost.Properties["Title"] = "First updated";
|
|
58
|
+
|
|
59
|
+
var operations = client.Chunk(new List<ChillOperation>
|
|
60
|
+
{
|
|
61
|
+
new() { Index = 0, Verb = ChillOperationVerb.CREATE, Entity = firstPost },
|
|
62
|
+
new() { Index = 1, Verb = ChillOperationVerb.CREATE, Entity = secondPost },
|
|
63
|
+
new() { Index = 2, Verb = ChillOperationVerb.UPDATE, Entity = updateFirstPost }
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
What this gives you:
|
|
68
|
+
|
|
69
|
+
- one HTTP request instead of three
|
|
70
|
+
- ordered execution through `Index`
|
|
71
|
+
- one combined response containing the processed operations
|
|
72
|
+
|
|
73
|
+
## 3. Wrap a chunk in one transaction
|
|
74
|
+
|
|
75
|
+
Use `transaction` and `commit` when all enclosed write operations must succeed or fail together.
|
|
76
|
+
|
|
77
|
+
```csharp
|
|
78
|
+
var blog = new ChillDtoEntity
|
|
79
|
+
{
|
|
80
|
+
ChillType = "Model.Blog",
|
|
81
|
+
Guid = Guid.NewGuid()
|
|
82
|
+
};
|
|
83
|
+
blog.Properties["Name"] = "Batch blog";
|
|
84
|
+
blog.Properties["Url"] = "https://example.local/batch-blog";
|
|
85
|
+
|
|
86
|
+
var post = new ChillDtoEntity
|
|
87
|
+
{
|
|
88
|
+
ChillType = "Model.Post",
|
|
89
|
+
Guid = Guid.NewGuid()
|
|
90
|
+
};
|
|
91
|
+
post.Properties["Title"] = "Batch post";
|
|
92
|
+
post.Properties["Blog"] = blog.Mock();
|
|
93
|
+
|
|
94
|
+
var transactionalOperations = client.Chunk(new List<ChillOperation>
|
|
95
|
+
{
|
|
96
|
+
new() { Index = 0, Verb = ChillOperationVerb.TRANSACTION },
|
|
97
|
+
new() { Index = 1, Verb = ChillOperationVerb.CREATE, Entity = blog },
|
|
98
|
+
new() { Index = 2, Verb = ChillOperationVerb.CREATE, Entity = post },
|
|
99
|
+
new() { Index = 3, Verb = ChillOperationVerb.COMMIT }
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Use this pattern only for the write operations that must share the same database transaction.
|
|
104
|
+
If one operation fails before `commit`, the transaction is not committed.
|
|
105
|
+
|
|
106
|
+
## 4. Autocomplete an entity DTO
|
|
107
|
+
|
|
108
|
+
`autocomplete` uses the same DTO style as `create`, `update`, and `delete`, but it calls `/api/chill/autocomplete`.
|
|
109
|
+
|
|
110
|
+
For entities, ChillSharp performs `OnAutocomplete(...)` without persisting changes:
|
|
111
|
+
|
|
112
|
+
- if the entity already exists, it is loaded from the current `DbContext`
|
|
113
|
+
- otherwise it is attached in `Added` state
|
|
114
|
+
- the autocomplete logic runs inside a temporary transaction
|
|
115
|
+
- the transaction is rolled back at the end, so the database is unchanged
|
|
116
|
+
|
|
117
|
+
This is useful for previewing computed values such as slugs, labels, derived text, or default field combinations.
|
|
118
|
+
|
|
119
|
+
```csharp
|
|
120
|
+
var draftBlog = new ChillDtoEntity
|
|
121
|
+
{
|
|
122
|
+
ChillType = "Model.Blog",
|
|
123
|
+
Guid = Guid.NewGuid()
|
|
124
|
+
};
|
|
125
|
+
draftBlog.Properties["Title"] = " My first ChillSharp blog ";
|
|
126
|
+
|
|
127
|
+
var autocompletedBlog = client.Autocomplete(draftBlog);
|
|
128
|
+
|
|
129
|
+
Console.WriteLine(autocompletedBlog.GetString("Title"));
|
|
130
|
+
Console.WriteLine(autocompletedBlog.GetString("Url"));
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Typical entity-side logic:
|
|
134
|
+
|
|
135
|
+
```csharp
|
|
136
|
+
public override void OnAutocomplete(IChillContext context)
|
|
137
|
+
{
|
|
138
|
+
base.OnAutocomplete(context);
|
|
139
|
+
|
|
140
|
+
Title = Title?.Trim();
|
|
141
|
+
|
|
142
|
+
if (string.IsNullOrWhiteSpace(Url) && !string.IsNullOrWhiteSpace(Title))
|
|
143
|
+
{
|
|
144
|
+
Url = "/blogs/" + Title.ToLowerInvariant().Replace(' ', '-');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## 5. Autocomplete a query DTO
|
|
150
|
+
|
|
151
|
+
Queries also use `/api/chill/autocomplete`, but they do not participate in the EF Core context transaction flow.
|
|
152
|
+
The query DTO is simply passed through `OnAutocomplete(...)` on the resolved `IChillQuery`.
|
|
153
|
+
|
|
154
|
+
This is useful for normalizing filters before `Query(...)`, for example:
|
|
155
|
+
|
|
156
|
+
- trimming text inputs
|
|
157
|
+
- expanding a search box into a full-text field
|
|
158
|
+
- setting default paging or sorting values
|
|
159
|
+
|
|
160
|
+
```csharp
|
|
161
|
+
var blogQuery = new ChillDtoQuery
|
|
162
|
+
{
|
|
163
|
+
ChillType = "Query.BlogQuery"
|
|
164
|
+
};
|
|
165
|
+
blogQuery.Properties["Title"] = " chillsharp ";
|
|
166
|
+
|
|
167
|
+
var autocompletedQuery = client.Autocomplete(blogQuery);
|
|
168
|
+
|
|
169
|
+
Console.WriteLine(autocompletedQuery.GetString("Title"));
|
|
170
|
+
Console.WriteLine(autocompletedQuery.GetString("FullTextSearch"));
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Typical query-side logic:
|
|
174
|
+
|
|
175
|
+
```csharp
|
|
176
|
+
public override void OnAutocomplete(IChillContext context)
|
|
177
|
+
{
|
|
178
|
+
base.OnAutocomplete(context);
|
|
179
|
+
|
|
180
|
+
Title = Title?.Trim();
|
|
181
|
+
|
|
182
|
+
if (!string.IsNullOrWhiteSpace(Title))
|
|
183
|
+
{
|
|
184
|
+
FullTextSearch = Title;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## 6. Choose the right API
|
|
190
|
+
|
|
191
|
+
- use `create`, `update`, and `delete` when the operation must change the database immediately
|
|
192
|
+
- use `chunk` when several operations should travel in one request
|
|
193
|
+
- use `transaction` plus `commit` inside `chunk` when multiple writes must be atomic
|
|
194
|
+
- use `autocomplete` when the server should calculate or normalize values without saving them
|
|
195
|
+
|
|
196
|
+
Next: [Back to the documentation index](../README.md)
|