Skip to content

Commit 54f6cba

Browse files
committed
Update docs
1 parent e79b61a commit 54f6cba

File tree

2 files changed

+58
-43
lines changed

2 files changed

+58
-43
lines changed

MyApp/_pages/autoquery/autogen.md

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
title: AutoQuery AutoGen CRUD Services
33
---
44

5-
Long time users of ServiceStack will know it's a staunch proponent of **code-first development** where your C# Types retains the master authority of your App's logic, although there are a number of times where you have to work with existing databases which would require significant effort to create the initial code-first Data Models. Historically we've pointed people to use [OrmLite's T4 Template Support](/ormlite/autogen-t4#t4-template-support) which provides a decent initial stab, however it's limited in its capability and offers a sub par development experience.
5+
Long time users of ServiceStack will know it's a staunch proponent of **code-first development** where your C# Types retains the master authority of your App's logic, although there are a number of times where you have to work with existing databases which would require significant effort to create the initial code-first Data Models.
6+
7+
### AutoGen vs TypeScript Data Models
8+
9+
AutoGen's approach relies on runtime C# reflection to inspect your RDBMS schema and dynamically register AutoQuery CRUD Services; if you prefer an alternative flow based on generating source code from exported DB metadata and TypeScript Data Models instead, see [Generate CRUD APIs and UIs for existing DBs](/autoquery/okai-db) which uses the `okai` tool.
610

711
<lite-youtube class="w-full mx-4 my-4" width="560" height="315" videoid="NaJ7TW-Q_pU" style="background-image: url('https://img.youtube.com/vi/NaJ7TW-Q_pU/maxresdefault.jpg')"></lite-youtube>
812

@@ -87,8 +91,8 @@ Then use the `x` dotnet tool to download all the AutoQuery & Crud Services for a
8791
`x csharp https://localhost:5001 -path /crud/all/csharp`
8892
:::
8993

90-
If you're running a mix of autogenerated AutoGen AutoQuery APIs with existing typed AutoQuery APIs, you can just
91-
generate the **new** Services with:
94+
If you're running a mix of autogenerated AutoGen AutoQuery APIs with existing typed AutoQuery APIs, you can just
95+
generate the **new** Services with:
9296

9397
:::sh
9498
x csharp https://localhost:5001 -path /crud/new/csharp
@@ -137,13 +141,13 @@ The generated `dtos.cs` includes AutoGen-specific options that can be used to ma
137141
```csharp
138142
/* Options:
139143
//...
140-
//IncludeCrudOperations:
144+
//IncludeCrudOperations:
141145
Schema: custom
142-
//NamedConnection:
143-
//NoCache:
144-
//IncludeTables:
145-
//ExcludeTables:
146-
//AuthSecret:
146+
//NamedConnection:
147+
//NoCache:
148+
//IncludeTables:
149+
//ExcludeTables:
150+
//AuthSecret:
147151
*/
148152
```
149153

@@ -246,9 +250,9 @@ public class ConfigureDb : IHostingStartup
246250
var dbFactory = new OrmLiteConnectionFactory(
247251
context.Configuration.GetConnectionString("DefaultConnection"),
248252
SqliteDialect.Provider);
249-
253+
250254
services.AddSingleton<IDbConnectionFactory>(dbFactory);
251-
255+
252256
services.AddPlugin(new AutoQueryFeature {
253257
MaxLimit = 1000,
254258
GenerateCrudServices = new GenerateCrudServices {
@@ -261,7 +265,7 @@ public class ConfigureDb : IHostingStartup
261265
}
262266
```
263267

264-
The [sqlite](https://gist.github.com/gistlyn/768d7b330b8c977f43310b954ceea668) gist registers an
268+
The [sqlite](https://gist.github.com/gistlyn/768d7b330b8c977f43310b954ceea668) gist registers an
265269
[OrmLite.Sqlite](https://github.com/ServiceStack/ServiceStack.OrmLite) RDBMS connection with our App which we want to configure to connect to a **northwind.sqlite** database:
266270

267271
```csharp
@@ -312,7 +316,7 @@ Once running you can view your Apps metadata page at `https://localhost:5001` to
312316

313317
#### Create Dart gRPC Console App
314318

315-
It's also now accessible via [ServiceStack's gRPC endpoint](/grpc/) which opens your generated Services up to [Google's high-performance gRPC ecosystem](https://grpc.io) which enables typed, high-performance integrations into exciting platforms like [Flutter](https://flutter.dev) which uses the [Dart](https://dart.dev) programming language to create Reactive, high-performance native Android and iOS Apps.
319+
It's also now accessible via [ServiceStack's gRPC endpoint](/grpc/) which opens your generated Services up to [Google's high-performance gRPC ecosystem](https://grpc.io) which enables typed, high-performance integrations into exciting platforms like [Flutter](https://flutter.dev) which uses the [Dart](https://dart.dev) programming language to create Reactive, high-performance native Android and iOS Apps.
316320

317321
We can test Dart's gRPC integration and development workflow in a new Dart Console App we can create with:
318322

@@ -329,7 +333,7 @@ dependencies:
329333
fixnum: ^0.10.11
330334
async: ^2.2.0
331335
protobuf: ^1.0.1
332-
grpc: ^2.1.3
336+
grpc: ^2.1.3
333337
```
334338
335339
When you save **pubspec.yaml** Dart's VS Code extension will automatically fetch any new dependencies which can also be manually run with:
@@ -418,9 +422,9 @@ void main(List<String> args) async {
418422

419423
Whilst the `AutoRegister = true` flag on its face may seem magical, it's simply an instruction that tells ServiceStack to register the **new** AutoQuery Services it already knows about and register them as if they were normal code-first Services that we had written ourselves.
420424

421-
More accurately, behind-the-scenes it uses the Metadata Type structure it constructed in generating the Services & Types, i.e. the same Types used to project into its Add ServiceStack Reference's generated C#, TypeScript, (and other languages) which are also the same Types that are manipulated when customizing code-generation, gets used to generate .NET Types in memory on Startup with Reflection.Emit.
425+
More accurately, behind-the-scenes it uses the Metadata Type structure it constructed in generating the Services & Types, i.e. the same Types used to project into its Add ServiceStack Reference's generated C#, TypeScript, (and other languages) which are also the same Types that are manipulated when customizing code-generation, gets used to generate .NET Types in memory on Startup with Reflection.Emit.
422426

423-
Barring any issues with the projection into IL, externally the end result is indistinguishable to a normal code-first ServiceStack Service manually created by a developer - An important point as to why these solutions compose well with the rest of ServiceStack, just as an AutoQuery Service is a normal ServiceStack Service, these auto generated & auto registered ServiceStack Services are regular Auto Query Services.
427+
Barring any issues with the projection into IL, externally the end result is indistinguishable to a normal code-first ServiceStack Service manually created by a developer - An important point as to why these solutions compose well with the rest of ServiceStack, just as an AutoQuery Service is a normal ServiceStack Service, these auto generated & auto registered ServiceStack Services are regular Auto Query Services.
424428

425429
The primary difference is that they only exist in a .NET Assembly in memory created on Startup, not in code so they're not "statically visible" to a C# compiler, IDE, tools, etc. But otherwise they're regular typed ServiceStack Services and can take advantage of the ecosystem around Services including [Add ServiceStack Reference](/add-servicestack-reference) & other Metadata Pages and Services, etc.
426430

@@ -462,8 +466,8 @@ Plugins.Add(new AutoQueryFeature {
462466
});
463467
```
464468

465-
These will generated Service Contracts & DTO Types with the Multitenancy [NamedConnection](/autoquery/rdbms#named-connection) & OrmLite `[Schema]` attribute required for routing AutoQuery Services to use the appropriate RDBMS connection of Schema.
466-
469+
These will generated Service Contracts & DTO Types with the Multitenancy [NamedConnection](/autoquery/rdbms#named-connection) & OrmLite `[Schema]` attribute required for routing AutoQuery Services to use the appropriate RDBMS connection of Schema.
470+
467471
Although there are potential conflicts if there are identical table names in each RDBMS/Schema as it has to go back and rewrite the Metadata References to use a non-ambiguous name, first tries using the NamedConnection, then the schema then a combination when both exists, if it's still ambiguous it gives up and ignores it. If you do run into conflicts, the recommendation is to "eject" the generated `.cs` sources and manually update them to use your preferred unique names.
468472

469473
### Customize Code Generation to include App Conventions
@@ -484,7 +488,7 @@ For an illustration of this in action, here's a typical scenario of how the Nort
484488

485489
- Controlling which Tables **not to generate Services for** in `ignoreTables`
486490
- Which tables not to generate **Write Crud Services** for in `readOnlyTables`
487-
- Which tables to **restrict access** to in different roles in `protectTableByRole`
491+
- Which tables to **restrict access** to in different roles in `protectTableByRole`
488492
- Example of **additional validation** to existing tables in `tableRequiredFields`
489493
- Adds the `[ValidateNotEmpty]` attribute to Services accessing the table and the `[Required]` OrmLite attribute for the Data Model DTO Type.
490494

@@ -506,12 +510,12 @@ Plugins.Add(new AutoQueryFeature {
506510
GenerateCrudServices = new GenerateCrudServices
507511
{
508512
DbFactory = dbFactory,
509-
ServiceFilter = (op,req) =>
513+
ServiceFilter = (op,req) =>
510514
{
511515
// Require all Write Access to Tables to be limited to Authenticated Users
512516
if (op.IsCrudWrite())
513517
{
514-
op.Request.AddAttributeIfNotExists(new ValidateRequestAttribute("IsAuthenticated"),
518+
op.Request.AddAttributeIfNotExists(new ValidateRequestAttribute("IsAuthenticated"),
515519
x => x.Validator == "IsAuthenticated");
516520
}
517521
@@ -532,7 +536,7 @@ Plugins.Add(new AutoQueryFeature {
532536
props.Each(x => x.AddAttribute(new ValidateNotEmptyAttribute()));
533537
}
534538
},
535-
TypeFilter = (type, req) =>
539+
TypeFilter = (type, req) =>
536540
{
537541
// Add OrmLite [Required] Attribute on Tables with Required Fields
538542
if (tableRequiredFields.TryGetValue(type.Name, out var requiredFields))
@@ -552,7 +556,7 @@ Plugins.Add(new AutoQueryFeature {
552556
Plugins.Add(new ValidationFeature()); // Enable Validation
553557
```
554558

555-
Additionally, the `TableSchemasFilter` can be used to modify the schema used by AutoGen to generate the types associated with your AutoQuery APIs.
559+
Additionally, the `TableSchemasFilter` can be used to modify the schema used by AutoGen to generate the types associated with your AutoQuery APIs.
556560
This gives you the opportunity to filter or modify the schema after they are pulled from the database.
557561
For example, we could `Remove` tables based on naming, or alter column definitions to assist with any schema issues.
558562

@@ -612,7 +616,7 @@ cd NorthwindCrud
612616
dotnet run
613617
```
614618

615-
This example App is also configured with other new features in incoming release including Crud Events in
619+
This example App is also configured with other new features in incoming release including Crud Events in
616620
[Startup.cs](https://github.com/NetCoreApps/NorthwindCrud/blob/master/Startup.cs):
617621

618622
```csharp
@@ -621,26 +625,26 @@ container.AddSingleton<ICrudEvents>(c => new OrmLiteCrudEvents(c.Resolve<IDbConn
621625
container.Resolve<ICrudEvents>().InitSchema();
622626
```
623627

624-
As well as support for dynamically generated db rules in
628+
As well as support for dynamically generated db rules in
625629
[Configure.Validation.cs](https://github.com/NetCoreApps/NorthwindCrud/blob/master/Configure.Validation.cs):
626630

627631
```csharp
628-
services.AddSingleton<IValidationSource>(c =>
632+
services.AddSingleton<IValidationSource>(c =>
629633
new OrmLiteValidationSource(c.Resolve<IDbConnectionFactory>()));
630634
631635
appHost.Resolve<IValidationSource>().InitSchema();
632636
```
633637

634-
To be able to test the custom code generation the example is pre-populated with 3 users with different roles in
638+
To be able to test the custom code generation the example is pre-populated with 3 users with different roles in
635639
[Configure.Auth.cs](https://github.com/NetCoreApps/NorthwindCrud/blob/master/Configure.Auth.cs):
636640

637641
```csharp
638642
// Register Users that don't exist
639643
void EnsureUser(string email, string name, string[] roles=null)
640644
{
641-
if (authRepo.GetUserAuthByUserName(email) != null)
645+
if (authRepo.GetUserAuthByUserName(email) != null)
642646
return;
643-
647+
644648
authRepo.CreateUserAuth(new UserAuth {
645649
Email = email,
646650
DisplayName = name,
@@ -657,7 +661,7 @@ Of which you can also find published on [NorthwindCrud's home page](https://gith
657661

658662
### AutoGen Customizations
659663

660-
AutoGen's [Instantly Servicify existing Systems](/servicify) feature works by automatically generating the AutoQuery & Crud APIs and Data Models for all tables in the configured RDBMS's. Further customization of the DataModel Names, the user-defined Route Path they're hosted at & the name of individual AutoQuery APIs for each operation using the `GenerateOperationsFilter`.
664+
AutoGen's [Instantly Servicify existing Systems](/servicify) feature works by automatically generating the AutoQuery & Crud APIs and Data Models for all tables in the configured RDBMS's. Further customization of the DataModel Names, the user-defined Route Path they're hosted at & the name of individual AutoQuery APIs for each operation using the `GenerateOperationsFilter`.
661665

662666
So if you had an existing table name called `applications` the default convention based names would be:
663667
- Data Model: `Applications`
@@ -716,16 +720,16 @@ As NorthwindCrud is [configured to use JWT](https://github.com/NetCoreApps/North
716720
```dart
717721
GrpcServicesClient createClient({CallOptions options}) {
718722
return GrpcServicesClient(ClientChannel('localhost', port:5054,
719-
options:ChannelOptions(credentials: ChannelCredentials.insecure())),
723+
options:ChannelOptions(credentials: ChannelCredentials.insecure())),
720724
options:options);
721725
}
722726
723727
void main(List<String> arguments) async {
724728
var authResponse = await createClient().postAuthenticate(
725729
Authenticate()..provider='credentials'..userName='[email protected]'..password='p@ss');
726730
727-
var authClient = createClient(options:CallOptions(metadata:{
728-
'Authorization': 'Bearer ${authResponse.bearerToken}'
731+
var authClient = createClient(options:CallOptions(metadata:{
732+
'Authorization': 'Bearer ${authResponse.bearerToken}'
729733
}));
730734
731735
var response = await authClient.getQueryCategory(QueryCategory());

MyApp/_pages/autoquery/okai-db.md

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,28 @@
22
title: Generate CRUD APIs and UIs for existing DBs
33
---
44

5-
A core piece of functionality in the [Text to Blazor CRUD App](/autoquery/text-to-blazor) feature is distilling an AI Prompt into TypeScript classes that can be [further customized](/autoquery/okai-models#customize-data-models)
6-
to generate AutoQuery CRUD APIs and Admin UIs for managing the underlying RDBMS tables.
5+
### AutoGen vs TypeScript Data Models
76

8-
## TypeScript Data Models
7+
AutoGen's approach relies on runtime C# reflection to inspect your RDBMS schema and dynamically register AutoQuery CRUD Services; this page instead documents an alternative flow based on generating source code from exported DB metadata and TypeScript Data Models using the `okai` tool. If you prefer the reflection-based approach, see [AutoQuery AutoGen CRUD Services](/autoquery/autogen).
98

10-
Using TypeScript is an effortless way to define data models, offering a DSL-like minimal boilerplate format that's human-friendly to read and write which can leverage TypeScript's powerful Type System is validated against the referenced [api.d.ts](https://okai.servicestack.com/api.d.ts) schema to provide a rich authoring experience
11-
with strong typing and intellisense - containing all the C# Types, interfaces, and attributes used in defining APIs, DTOs and Data Models.
9+
## Generate CRUD APIs from TypeScript Data Models
10+
11+
A core feature of the [okai](/autoquery/okai-models) tool is the ability to convert [customized TypeScript Data Models](/autoquery/okai-models#customize-data-models) into C# AutoQuery CRUD APIs, RDBMS DataModel tables and DB Migrations.
12+
13+
This enables a flexible way to generate AutoQuery CRUD APIs for existing RDBMS tables, by:
14+
15+
1. Exporting the existing RDBMS metadata to json
16+
2. Use `okai` to convert the json metadata into TypeScript Data Models
17+
3. Perform any customizations to the TypeScript Data Model as needed
18+
4. Use `okai` to generate the AutoQuery CRUD APIs, RDBMS DataModel tables and DB Migrations
19+
20+
### Why TypeScript?
21+
22+
Using TypeScript is an effortless way to define data models, offering a DSL-like minimal boilerplate format that's human-friendly to read and write which can leverage TypeScript's powerful Type System is validated against the referenced [api.d.ts](https://okai.servicestack.com/api.d.ts) schema to provide a rich authoring experience with strong typing and intellisense - containing all the C# Types, interfaces, and attributes used in defining APIs, DTOs and Data Models.
1223

1324
### Blueprint for Code Generation
1425

15-
The TypeScript Data Models serve as the blueprint for generating everything needed to support the feature
26+
The TypeScript Data Models serve as the blueprint for generating everything needed to support the feature
1627
in your App, including the AutoQuery **CRUD APIs**, **Admin UIs** and **DB Migrations** that can re-create the necessary tables from scratch.
1728

1829
## 1. Generate RDBMS Metadata
@@ -34,7 +45,7 @@ This task can then be run from the command line with:
3445
dotnet run --AppTasks=App.json
3546
:::
3647

37-
Which generates `App_Data/App.json` containing the table definition metadata for all tables in
48+
Which generates `App_Data/App.json` containing the table definition metadata for all tables in
3849
the specified RDBMS, e.g:
3950

4051
```json
@@ -74,7 +85,7 @@ the specified RDBMS, e.g:
7485

7586
### Different Connection or DB Schema
7687

77-
If you prefer to generate the metadata for a different connection or schema, you can create a new AppTask
88+
If you prefer to generate the metadata for a different connection or schema, you can create a new AppTask
7889
with your preferred `namedConnection` and/or `schema`, e.g:
7990

8091
```csharp
@@ -92,11 +103,11 @@ dotnet run --AppTasks=Sales.json
92103
## 2. Generate TypeScript Data Models
93104

94105
The next step is to generate TypeScript Data Models from the captured metadata which can be done with the `okai` tool
95-
by running the `convert` command with the path to the `App.json` JSON table definitions which will generate the
106+
by running the `convert` command with the path to the `App.json` JSON table definitions which will generate the
96107
TypeScript Data Models to stdout which can be redirected to a file in your **ServiceModel** project, e.g:
97108

98109
:::sh
99-
npx okai convert App_Data/App.json > ../MyApp.ServiceModel/App.d.ts
110+
npx okai convert App_Data/App.json > ../MyApp.ServiceModel/App.d.ts
100111
:::
101112

102113
## 3. Generate CRUD APIs and Admin UIs

0 commit comments

Comments
 (0)