Spiderly.SourceGenerators
19.1.0
dotnet add package Spiderly.SourceGenerators --version 19.1.0
NuGet\Install-Package Spiderly.SourceGenerators -Version 19.1.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Spiderly.SourceGenerators" Version="19.1.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Spiderly.SourceGenerators" Version="19.1.0" />
<PackageReference Include="Spiderly.SourceGenerators" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Spiderly.SourceGenerators --version 19.1.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Spiderly.SourceGenerators, 19.1.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#addin nuget:?package=Spiderly.SourceGenerators&version=19.1.0
#tool nuget:?package=Spiderly.SourceGenerators&version=19.1.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Spiderly.SourceGenerators
Spiderly.SourceGenerators generates a lot of features for both .NET and Angular apps by using attributes on EF Core entities. Its goal is to let developers focus solely on writing specific logic, without worrying about boilerplate code.
Quickstart
- Generate the app structure using Spiderly CLI.
- Add entities to the project (inside {appName}.Business → Entities folder):
- If crud operations can be performed on the entity from the application, it should inherit
BusinessObject<ID>
, if the entity is only for reading from the database (e.g.Gender
entity), it should inheritReadonlyObject<ID>
. For BusinessObject entities, the necessary methods for basic crud operations will be generated, while e.g. for ReadonlyObject entities Create, Update, Delete methods will not be generated. For ReadonlyObject<T> we don't make CreatedAt and Version properties. - Example of the EF Core entity:
namespace PlayertyLoyals.Business.Entities
{
[TranslateSingularSrLatnRS("Korisnik")] // Where necessary, the entity UserExtended will be translated into Serbian as "Korisnik"
public class UserExtended : BusinessObject<long>, IUser
{
[UIControlWidth("col-12")] // On the UI this control will be displayed over the entire width of the screen for any device size (by default it is half, then from a certain number of pixels the whole screen)
[DisplayName] // A Property with this attribute will be used as a display name for the class it is in (e.g. when we display the UserExtended list in the dropdown, their emails will be used for display). If you don't put this property anywhere, the Id will be taken by default.
[StringLength(70, MinimumLength = 5)] // This attribute is already built in EF Core, but apart from that, we also use it to generate validations (Backend and Frontend)
[Required] // This attribute is already built in EF Core, but apart from that, we also use it to generate validations (Backend and Frontend)
public string Email { get; set; }
[UIDoNotGenerate] // We don't show this control to the end user on the UI
public bool? HasLoggedInWithExternalProvider { get; set; }
public DateTime? BirthDate { get; set; }
[UIControlType(nameof(UIControlTypeCodes.Dropdown))] // This many to one property will be handled with dropdown on the UI (the necessary structure will be generated on the Backend to support it too)
[SetNull] // When referenced Gender is deleted this property will be set to null
[WithMany(nameof(Gender.Users))] // Connected one to many property
public virtual Gender Gender { get; set; }
[BusinessServiceDoNotGenerate] // Frontend structure and controller method will be generated, but method inside BusinessServiceGenerated will not
[UIControlType(nameof(UIControlTypeCodes.MultiSelect))] // This many to many property will be handled with multiselect on the UI (the necessary structure will be generated on the Backend to support it too)
public virtual List<Role> Roles { get; } = new(); // M2M
}
}
- Write custom logic,
- This is an example for the Notification entity, on the administration page of the entity we want to add a button, click on which we will send an email notification to users:
import { HttpClient } from '@angular/common/http';
import { ChangeDetectorRef, Component, KeyValueDiffers, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { TranslocoService } from '@jsverse/transloco';
import { Notification } from 'src/app/business/entities/business-entities.generated';
import { ApiService } from 'src/app/business/services/api/api.service';
import { BaseFormCopy, SpiderlyFormGroup, SpiderlyFormControl, SpiderlyButton, SpiderlyMessageService, BaseFormService } from 'spiderly';
@Component({
selector: 'notification-details',
templateUrl: './notification-details.component.html',
styles: [],
})
export class NotificationDetailsComponent extends BaseFormCopy implements OnInit {
notificationFormGroup = new SpiderlyFormGroup<Notification>({});
isMarkedAsRead = new SpiderlyFormControl<boolean>(true, {updateOn: 'change'})
additionalButtons: SpiderlyButton[];
constructor(
protected override differs: KeyValueDiffers,
protected override http: HttpClient,
protected override messageService: SpiderlyMessageService,
protected override changeDetectorRef: ChangeDetectorRef,
protected override router: Router,
protected override route: ActivatedRoute,
protected override translocoService: TranslocoService,
protected override baseFormService: BaseFormService,
private apiService: ApiService,
) {
super(differs, http, messageService, changeDetectorRef, router, route, translocoService, baseFormService);
}
override ngOnInit() {
this.additionalButtons = [
{label: this.translocoService.translate('SendEmailNotification'), onClick: this.sendEmailNotification, icon: 'pi pi-send'}
];
}
// NOTE: We must to do it like arrow function
sendEmailNotification = () => {
this.apiService.sendNotificationEmail(this.notificationFormGroup.controls.id.value, this.notificationFormGroup.controls.version.value).subscribe(() => {
this.messageService.successMessage(this.translocoService.translate('SuccessfulAttempt'));
});
}
override onBeforeSave = (): void => {
this.saveBody.isMarkedAsRead = this.isMarkedAsRead.value;
}
}
- Example of adding custom code to html:
<ng-container *transloco="let t">
<spiderly-card [title]="t('PartnerNotification')" icon="pi pi-bell">
<spiderly-panel [isFirstMultiplePanel]="true" [showPanelHeader]="false">
<panel-body>
Custom HTML logic!
</panel-body>
</spiderly-panel>
<notification-base-details
[formGroup]="formGroup"
[notificationFormGroup]="notificationFormGroup"
(onSave)="onSave()"
[isLastMultiplePanel]="true"
[additionalButtons]="additionalButtons"
/>
</spiderly-card>
</ng-container>
Entity Attributes
Required
- This attribute is already built in EF Core, but apart from that, we also use it to generate validations (Backend and Frontend).
- When it's used on the enumerable property (for now, only in combination with
UIOrderedOneToMany
attribute) will not allow saving an empty list.
StringLength
- This attribute is already built in EF Core, but apart from that, we also use it to generate validations (Backend and Frontend).
GreaterThanOrEqualTo
- Set this attribute to the numeric properties only.
CustomValidator
- If you cannot achieve something with built in fluent validations, you can write custom on the class.
- e.g.
[CustomValidator("RuleFor(x => x.Name).NotEmpty();")]
DisplayName
- A Property with this attribute will be used as a display name for the class it is in (e.g. when we display the
UserExtended
list in the dropdown, their emails will be used for display). If you don't put this property anywhere, the Id will be taken by default. - Don't use nameof, because source generator will take only "Email" if you pass nameof(User.Email)
- Pass the parameter only if the display name is like this: User.Email
BlobName
- Set this attribute to a property that serves as a pointer to the file identifier in azure storage.
Controller
- Set this attribute to the entities for which you do not want the controller to be called {entityName}Controller, but to give it a custom name and possibly connect more entities to that controller.
ExcludeFromDTO
- Set this attribute to the property you don't want generated in the DTO.
IncludeInDTO
- Set this attribute to the property you want generated in the DTO.
- It only makes sense for enumerable properties (because they are not generated in a DTO by default).
- The generated property in DTO will not be included in the mapping library.
ExcludeServiceMethodsFromGeneration
- All the logic that should be generated in the
BusinessServiceGenerated
class for this property will not be generated.
GenerateCommaSeparatedDisplayName
- Set this attribute to the enumerable property for which you want the List<string> property to be generated in the DTO.
- It will be filled with display names using mapper.
- It is used to display comma separated display names in a table on the UI.
WithMany
- Set to the many to one property.
- Pass enumerable parameter in order to know which enumerable property on the other side many to one property connects to.
ManyToOneRequired
- Set to the many to one property to perform a
cascade
delete. - We also use it to generate validations (Backend and Frontend).
- The parent entity cannot exist without the property which has this attribute.
SetNull
- Set to the many to one property to perform a
set null
delete.
M2MEntity
- Set to a property in the M2M class that represents a reference to another entity.
- As a parameter, you need to pass an enumerable property from the referenced entity.
M2MMaintanceEntity
- Set to a property in the M2M class that represents a reference to another entity.
- M2M relationship will be maintained through this referenced entity, both on the UI and on the backend.
- As a parameter, you need to pass an enumerable property from the referenced entity.
SimpleManyToManyTableLazyLoad
- Set to the enumerable property which represents a navigation to other side of M2M relationship.
- Will generate such a structure on the backend and frontend that the many-to-many relationship is maintained using a lazy loading table.
UI Attributes
These attributes are used exclusively for the UI.
UIControlType
- We try to conclude what type of controller should be on the front based on the property data type, but in some cases it is impossible
- Such as e.g. with the
color-picker
UI control type, the data type in C# is string, but that doesn't tell us enough. - e.g.
[UIControlType(nameof(UIControlTypeCodes.ColorPick))]
public string PrimaryColor { get; set; }
UIControlWidth
- Set to the property whose default width you want to change.
- e.g.
[UIControlWidth("col-12")]
, in the example, the width control will always be full screen. - Default values for different control types are:
-
- file, text-area, color-picker, multiselect, multiautocomplete, table, editor:
col-12
- file, text-area, color-picker, multiselect, multiautocomplete, table, editor:
-
- everything else:
col-12 md:col-6
- everything else:
UIDoNotGenerate
- This attribute can be set on an entity as well as on a property.
- If it is set on an entity, that entity will not be generated at all for administration on the UI.
- If it is set on a property, only that property will not be displayed.
UIOrderedOneToMany
- Set to the one to many property.
- Will generate such a structure on the backend and frontend that the one-to-many relationship is maintained using ordered list.
- For this way of maintenance on the entity, on the other hand, you must have the property
OrderNumber
, e.g.
[UIDoNotGenerate]
[Required]
public int OrderNumber { get; set; }
UIPanel
- With this attribute you determine in which panel the UI control will be located.
- By default all controls are inside the "Details" panel.
UIPropertyBlockOrder
- With this control, you determine the order in which controls will be displayed on the UI.
- The controls are displayed in the order you specified the properties on the entity (except
file
,text-area
,editor
,table
control types, they are always displayed last in the written order).
UITableColumn
- Set to the enumerable property in combination with
SimpleManyToManyTableLazyLoad
attribute. - e.g.
#region UITableColumn
[UITableColumn(nameof(PartnerUserDTO.UserDisplayName))]
[UITableColumn(nameof(PartnerUserDTO.Points))]
[UITableColumn(nameof(PartnerUserDTO.TierDisplayName))]
[UITableColumn(nameof(PartnerUserDTO.CheckedSegmentationItemsCommaSeparated), "Segmentation")]
[UITableColumn(nameof(PartnerUserDTO.CreatedAt))]
#endregion
[SimpleManyToManyTableLazyLoad]
public virtual List<PartnerUser> Recipients { get; } = new(); // M2M
Translation Attributes
TranslatePluralEn
- e.g.
Users
TranslatePluralSrLatnRS
- e.g.
Korisnici
TranslateExcelEn
- If you don't pass a property for this attribute, but you do pass for plural, we'll use that translation.
- e.g.
Users.xlsx
TranslateExcelSrLatnRS
- If you don't pass a property for this attribute, but you do pass for plural, we'll use that translation.
- e.g.
Korisnici.xlsx
TranslateSingularEn
- e.g.
User
TranslateSingularSrLatnRS
- e.g.
Korisnik
There are no supported framework assets in this package.
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- CodegenCS.Core (>= 3.3.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
19.1.0 | 129 | 6/23/2025 |
19.1.0-preview.6 | 102 | 6/23/2025 |
19.1.0-preview.5 | 101 | 6/23/2025 |
19.1.0-preview.4 | 106 | 6/23/2025 |
19.1.0-preview.3 | 103 | 6/23/2025 |
19.1.0-preview.2 | 104 | 6/23/2025 |
19.1.0-preview.1 | 109 | 6/23/2025 |
19.1.0-preview.0 | 106 | 6/22/2025 |
19.0.9 | 123 | 6/14/2025 |
19.0.8 | 118 | 6/14/2025 |
19.0.7 | 119 | 6/14/2025 |
19.0.6 | 150 | 6/14/2025 |
19.0.5 | 154 | 6/14/2025 |
19.0.4 | 162 | 6/14/2025 |
19.0.3 | 141 | 6/6/2025 |
19.0.2 | 88 | 5/30/2025 |
19.0.1 | 82 | 5/30/2025 |
19.0.0 | 104 | 5/23/2025 |
1.0.18 | 148 | 5/4/2025 |
1.0.17 | 145 | 4/29/2025 |
1.0.16 | 143 | 4/28/2025 |
1.0.15 | 149 | 4/28/2025 |
1.0.14 | 147 | 4/28/2025 |
1.0.13 | 97 | 4/12/2025 |
1.0.12 | 94 | 4/11/2025 |