### TypeScript API Controller Implementation Example Source: https://context7_llms Demonstrates a full API controller setup using `@myre/engine/api` decorators. It showcases customer-scoped, nested collection, and individual resource controllers, illustrating routing, authentication (`@Auth`), authorization (`@Rights`), versioning (`@Version`), and API documentation (`@ApiDescription`, `@ApiOperation`). It also shows dependency injection (`inject`) and parameter handling (`@Body`, `@Query`). ```TypeScript import { Controller, Get, Post, Put, Delete, Body, ReturnType, Auth, Rights, Version, ApiDescription, ApiOperation, Query, inject, Scope, SCOPES } from '@myre/engine/api'; import { PermissionRight } from '@myre/engine/models'; import { PermissionResource } from '@myre/engine/models/am'; import { PrimitiveReferences } from '@myre/engine/api'; // Customer-scoped root controller @Controller('/customers/:customerId') @Scope(SCOPES.SINGLETON) @Auth(CustomerAuth) // CustomerAuth extracts customerId and populates req.customer @ApiDescription({ description: 'Customer management operations' }) export class CustomerApi { private readonly _customerService = inject(CustomerService); @Get('/') @Rights([ { resource: PermissionResource.CUSTOMER, right: PermissionRight.READ } ]) @Version('1.0.0') @ApiOperation({ summary: 'Get customer details' }) @ReturnType(Customer) public getCustomer(req: Request): Promise { // req.customer populated by CustomerAuth return this._customerService.getCustomer(req.customer); } } // Nested collection controller under customer scope @Controller('/users') @Scope(SCOPES.SINGLETON) @ApiDescription({ description: 'User management operations' }) export class UsersApi { private readonly _userService = inject(UserService); @Get('/') @Rights([ { resource: PermissionResource.USER, right: PermissionRight.READ } ]) @Version('1.0.0') @ApiOperation({ summary: 'Get all users', description: 'Retrieves a list of all users with optional filtering' }) @ReturnType(User, { isArray: true }) public getUsers( req: Request, @Query('search', String) search?: string, @Query('limit', Number) limit?: number, @Query('active', Boolean) active?: boolean ): Promise { return this._userService.getUsers({ loggedUser: req.user, customer: req.customer }, { search, limit, active }); } @Post('/') @Rights([ { resource: PermissionResource.USER, right: PermissionRight.WRITE } ]) @Version('1.0.0') @ApiOperation({ summary: 'Create a new user' }) @ReturnType(User) public createUser( req: Request, @Body(CreateUser) body: CreateUser ): Promise { return this._userService.createUser({ loggedUser: req.user, customer: req.customer }, body); } } // Individual user controller @Controller('/') @Auth(UserAuth) // Populates req.user @ApiDescription({ description: 'Individual user operations' }) export class UserApi { private readonly _userService = inject(UserService); @Delete('/') @Rights([ { resource: PermissionResource.USER, right: PermissionRight.DELETE } ]) @Version('1.0.0') @ReturnType(PrimitiveReferences.Boolean) public deleteUser(req: Request): Promise { // req.user populated by UserAuth await this._userService.deleteUser(req.user); return true; } } ``` -------------------------------- ### Integrating Query Parameters in TypeScript API Controllers Source: https://context7_llms Illustrates the method for integrating query parameters into API endpoints using individual @Query() decorators. This example shows how to define optional search (string), limit (number), and status (enum UserStatus) parameters for a GET request. ```TypeScript @Controller('/users') @Auth(CustomerAuth) export class UsersApi { private readonly _userService = inject(UserService); @Get('/') @ReturnType(User, { isArray: true }) public getUsers( req: Request, @Query('search', String) search?: string, @Query('limit', Number) limit?: number, @Query('status', String) status?: UserStatus ): Promise { return this._userService.getUsers({ loggedUser: req.user, customer: req.customer }, { search, limit, status }); } } ``` -------------------------------- ### Implementing Two Controllers Pattern for Collections Source: https://context7_llms Shows the 'Two Controllers Pattern' for API design, using plural names for collection controllers. It demonstrates how @Auth(CustomerAuth) can be applied at the root level for customer-scoped routes and how nested controllers inherit context. Includes examples for getting all customers and users, and creating a new user within a customer's scope, passing entities as a scope object to the service layer. ```TypeScript // Customer-scoped root controller @Controller('/customers/:customerId') @Auth(CustomerAuth) // CustomerAuth extracts customerId and populates req.customer export class CustomerApi { @Get('/') @ReturnType(Customer) public getCustomer(req: Request): Promise { // req.customer populated by CustomerAuth return req.customer; } } // Nested collection controller under customer scope @Controller('/users') export class UsersApi { private readonly _userService = inject(UserService); // GET /customers/:customerId/users - Get all users for customer @Get('/') @ReturnType(User, { isArray: true }) public getUsers(req: Request): Promise { // Controller extracts entities from request and passes them as scope object return this._userService.getUsers({ loggedUser: req.user, customer: req.customer }); } // POST /customers/:customerId/users - Create a new user @Post('/') @ReturnType(User) public createUser( req: Request, @Body(CreateUser) body: CreateUser ): Promise { // Scope object consolidates related entities for service layer return this._userService.createUser({ loggedUser: req.user, customer: req.customer }, body); } } ``` -------------------------------- ### Apply Trust Mode for Pre-Validated Data Source: https://context7_llms Provides quick examples for using trust mode when initializing entities. It shows when to safely apply trust mode (for database results or already validated external data) and when to avoid it (for direct user input). ```typescript // ✅ Use trust mode for database data (already validated) const user = new UserEntity().init(dbResult, { trust: true }); // ✅ Use trust mode for validated external data const user = new UserEntity().init(validatedApiData, { trust: true }); // ❌ Never use trust mode for user input const user = new UserEntity().init(userInput); // No trust mode ``` -------------------------------- ### Implement a Complete Authentication Class Source: https://context7_llms Provides a full example of an `OperationAuth` class, demonstrating how to implement the `Authorizer` interface. It shows dependency injection, asynchronous authorization logic, parameter extraction using `@Param()`, and custom error handling to determine access based on operation existence. ```TypeScript import { Service, Param } from '@myre/engine/api'; import { BaseApi, Authorizer } from '@myre/engine/api'; @Service() export class OperationAuth implements Authorizer { private readonly _operationService = inject(OperationService); public async authorize( req: Request, res: Response, @Param('operationId', Number) operationId: number, ): Promise { const operation = await this._operationService.getOperation(operationId); if (!operation) { this._handleError(req, res, new OperationNotFoundError(operationId)); return null; } req.operation = operation; return true; } } ``` -------------------------------- ### Validation Decorators Reference for @myre/engine/validators Source: https://context7_llms A comprehensive list of validation decorators provided by the `@myre/engine/validators` library, detailing their purpose, signature, and example usage for various data types and validation needs. ```APIDOC @IsString() Source: @myre/engine/validators Signature: (maxLength?: number, validationOptions?) Purpose: String validation with optional max length (default: 255) Example: @IsString(50) @IsText() Source: @myre/engine/validators Signature: (validationOptions?) Purpose: Unlimited text validation Example: @IsText() @IsInteger() Source: @myre/engine/validators Signature: (validationOptions?) Purpose: Integer validation Example: @IsInteger() @IsSmallInt() Source: @myre/engine/validators Signature: (validationOptions?) Purpose: Small integer validation (more efficient) Example: @IsSmallInt() @IsBigInt() Source: @myre/engine/validators Signature: (validationOptions?) Purpose: Big integer validation Example: @IsBigInt() @IsDecimal() Source: @myre/engine/validators Signature: ([precision, scale]?, validationOptions?) Purpose: Decimal validation with optional precision/scale Example: @IsDecimal([10, 2]) @IsNumeric() Source: @myre/engine/validators Signature: (validationOptions?) Purpose: Numeric validation (less precise than IsDecimal) Example: @IsNumeric() @IsReal() Source: @myre/engine/validators Signature: (validationOptions?) Purpose: Real number validation Example: @IsReal() @IsDoublePrecision() Source: @myre/engine/validators Signature: (validationOptions?) Purpose: Double precision floating point validation Example: @IsDoublePrecision() @IsDateOnly() Source: @myre/engine/validators Signature: (validationOptions?) Purpose: Date validation (must be start of day) Example: @IsDateOnly() @IsDateOnlyUnrestricted() Source: @myre/engine/validators Signature: (validationOptions?) Purpose: Date validation (start of day) without DWH date range restrictions Example: @IsDateOnlyUnrestricted() @ParseDate() Source: @myre/engine/validators Signature: (validationOptions?) Purpose: Parse and validate date values Example: @ParseDate() @ParseDateOnly() Source: @myre/engine/validators Signature: (validationOptions?) Purpose: Parse and validate date-only values Example: @ParseDateOnly() @IsInstance() Source: @myre/engine/validators Signature: (targetType, validationOptions?) or (types[], picker, validationOptions?) Purpose: Nested entity validation Example: @IsInstance(AddressEntity) @IsInstanceArray() Source: @myre/engine/validators Signature: (targetType, validationOptions?) or (types[], picker, validationOptions?) Purpose: Array of nested entities validation Example: @IsInstanceArray(ContactEntity) @IsOptional() Source: @myre/engine/validators Signature: (options?: {nullable: boolean}, validationOptions?: ValidationOptions) Purpose: Makes field optional (allows undefined/null) Example: @IsOptional() @IsBIC() Source: @myre/engine/validators Signature: (validationOptions?) Purpose: BIC (Bank Identifier Code) validation Example: @IsBIC() ``` -------------------------------- ### Trust Mode Usage Examples Source: https://context7_llms This snippet provides examples of when to correctly and incorrectly use trust mode. It highlights that trust mode is suitable for already validated data like database results or validated API responses, but should never be used for unvalidated user input. ```typescript // ✅ Good - Database data (already validated) const user = new UserEntity().init(dbResult, { trust: true }); // ✅ Good - Validated API response const user = new UserEntity().init(validatedApiData, { trust: true }); // ❌ Bad - User input (needs validation) const user = new UserEntity().init(userInput, { trust: true }); // Never do this ``` -------------------------------- ### Define Basic User Entity with Validation Source: https://context7_llms This example illustrates how to define a simple `UserEntity` by extending `BaseValidatorClass`. It applies `@IsInteger` and `@Min` for the `id` property and `@IsString` for the `name` property, showcasing fundamental validation decorator usage. ```typescript import { BaseValidatorClass, IsString, IsInteger } from '@myre/engine/validators'; import { Min } from 'class-validator'; export class UserEntity extends BaseValidatorClass { @IsInteger() @Min(1) public id: number; @IsString() public name: string; } ``` -------------------------------- ### TypeScript Individual User Resource Controller Source: https://context7_llms This TypeScript controller defines API endpoints for managing a single user resource. It demonstrates the use of decorators like @Controller, @Auth, @Get, @Put, and @Delete to handle GET, PUT, and DELETE operations for a specific user, leveraging a 'scope' object to consolidate request-related entities such as loggedUser, targetUser, and customer. ```typescript // Individual user controller nested under customer scope @Controller('/:userId') @Auth(UserAuth) // UserAuth extracts userId and populates req.user export class UserApi { private readonly _userService = inject(UserService); // GET /customers/:customerId/users/:userId - Get specific user @Get('/') @ReturnType(User) public getUser(req: Request): Promise { // Controller consolidates entities from request into scope object return this._userService.getUser({ loggedUser: req.user, targetUser: req.user, // In this case, same user customer: req.customer }); } // PUT /customers/:customerId/users/:userId - Update specific user @Put('/') @ReturnType(User) public updateUser( req: Request, @Body(UpdateUser) body: UpdateUser ): Promise { // Scope object groups all entities needed for the operation return this._userService.updateUser({ loggedUser: req.user, targetUser: req.user, customer: req.customer }, body); } // DELETE /customers/:customerId/users/:userId - Delete specific user @Delete('/') @ReturnType(PrimitiveReferences.Boolean) public deleteUser(req: Request): Promise { // Even single entity operations benefit from scope pattern consistency await this._userService.deleteUser({ loggedUser: req.user, targetUser: req.user, customer: req.customer }); return true; } } ``` -------------------------------- ### Handling File Uploads with @File() Decorator Source: https://context7_llms Demonstrates how to use the @File() decorator to handle file uploads in an API endpoint. It includes an example of validating file presence and throwing a custom error if the file is missing. ```TypeScript import { FileAndMetadata } from '@myre/engine/api'; import { AbstractError } from '@myre/engine/core'; export class MissingFileError extends AbstractError { constructor() { super(50007, { en: 'File is required for this operation', fr: 'Un fichier est requis pour cette opération', }); } } @Controller('/:userId') @Auth(UserAuth) export class UserApi { private readonly _userService = inject(UserService); @Post('/upload-avatar') @ReturnType(User) public uploadAvatar( req: Request, @File() file: FileAndMetadata ): Promise { if (!file) { throw new MissingFileError(); } return this._userService.uploadAvatar(req.user, file); } } ``` -------------------------------- ### Define GET Endpoint with @Get() Decorator Source: https://context7_llms The `@Get()` decorator is used to define an HTTP GET endpoint within a controller. It specifies the route path and can be combined with `@ReturnType()` to declare the expected response type. Examples show retrieving a list of users or a single user. ```typescript @Controller('/users') export class UsersApi { private readonly _userService = inject(UserService); @Get('/') @ReturnType(User, { isArray: true }) public getUsers(req: Request): Promise { return this._userService.getUsers(req.customer); } } @Controller('/:userId') @Auth(UserAuth) export class UserApi { private readonly _userService = inject(UserService); @Get('/') @ReturnType(User) public getUser(req: Request): Promise { // req.user populated by Auth class return this._userService.getUser(req.user); } } ``` -------------------------------- ### Database Integrity Mismatch Log Output Source: https://context7_llms Example log output indicating a database integrity mismatch error, specifically a nullable column discrepancy between the sequence definition and the database schema. ```Log [integrity.db.mismatch] ➥ Details: {"integrity":{"tableName":"corporate","columnName":"address_id","seqIsNullable":false,"dbIsNullable":true}} ``` -------------------------------- ### Run Tests for Specific Modules in MYRE Engine Source: https://context7_llms This command demonstrates how to run tests for specific modules within the MYRE Engine using the `-m` or `--module` flag. It also shows how to run tests for multiple modules, exclude modules using `-e` or `--exclude`, and get help with `-h`. ```Shell npm run test:dev -- -m pdf ``` ```Shell npm run test:dev -- -m pdf -m excel ``` ```Shell npm run test -- -h ``` -------------------------------- ### Specifying Authorization Requirements with @Rights() in TypeScript Source: https://context7_llms Details the use of the @Rights() decorator to define authorization requirements based on specific resources and rights (e.g., PermissionResource.USER, PermissionRight.READ/WRITE). It shows examples for both GET and POST operations. ```typescript import { PermissionRight } from '@myre/engine/models'; import { PermissionResource } from '@myre/engine/models/am'; @Controller('/users') export class UsersApi { private readonly _userService = inject(UserService); @Get('/') @Rights([ { resource: PermissionResource.USER, right: PermissionRight.READ } ]) public getUsers(req: Request): Promise { // implementation } @Post('/') @Rights([ { resource: PermissionResource.USER, right: PermissionRight.WRITE } ]) public createUser( req: Request, @Body(CreateUser) body: CreateUser ): Promise { // implementation } } ``` -------------------------------- ### Implement Status Validation for User Creation in TypeScript Source: https://context7_llms This example demonstrates how to apply `EntityStatus.NEW` validation to a `UserEntityStatusCreate` class. It ensures that new user entities are correctly marked with the 'NEW' status upon creation, leveraging `@IsEnum` and `@Equals` decorators. ```TypeScript export class UserEntityStatusCreate extends CreateUserDataEntity { @IsEnum(EntityStatus) @Equals(EntityStatus.NEW) @SwaggerExtraInfo({ 'x-enumName': 'EntityStatus' }) public entityStatus: EntityStatus.NEW; } ``` -------------------------------- ### Register Service for Dependency Injection with @Service() in Myre Engine Source: https://context7_llms The @Service() decorator registers a class for dependency injection, enabling the framework to manage its instances and dependencies. It demonstrates how to inject other services and define methods, including an example with a scope pattern for consolidating related entities and adding metadata for service description. ```TypeScript import { Service, inject } from '@myre/engine/api'; @Service() export class UserService { private readonly _userDao = inject(UserDao); // Scope pattern: consolidate related entities into single parameter public async getUsers(scope: { loggedUser: User; customer: Customer; }): Promise { return this._userDao.findAll(scope); } } // Service with metadata @Service({ summary: 'User management service' }) export class UserService { private readonly _userDao = inject(UserDao); // Service implementation } ``` -------------------------------- ### Define Currency and Amount Financial Entities in TypeScript Source: https://context7_llms This example illustrates the creation of an `AmountEntity` with `amount` (decimal) and `currency` (string) fields. It then shows how this `AmountEntity` can be integrated into an `InvoiceEntity` to represent financial data, such as a total amount, ensuring consistent validation for monetary values. ```TypeScript export class AmountEntity extends BaseValidatorClass { @IsDecimal([10, 2]) public amount: number; @IsString(3) @SwaggerExtraInfo({ examples: ['EUR', 'USD'] }) public currency: string; } export class InvoiceEntity extends BaseValidatorClass { @IsInteger() @Min(1) public id: number; @IsInstance(AmountEntity) public totalAmount: AmountEntity; } ``` -------------------------------- ### Response Typing with @ReturnType() Decorator in TypeScript Source: https://context7_llms Illustrates the use of the @ReturnType() decorator to specify response types for SDK generation and documentation. This includes examples for returning an array of entities, a single entity, and primitive types like boolean, ensuring consistent API responses. ```TypeScript // Collection controller @Controller('/users') @Auth(CustomerAuth) export class UsersApi { private readonly _userService = inject(UserService); @Get('/') @ReturnType(User, { isArray: true }) // Array of entities public getUsers(req: Request): Promise { return this._userService.getUsers({ loggedUser: req.user, customer: req.customer }); } } // Individual user controller @Controller('/:userId') @Auth(UserAuth) // UserAuth populates req.user export class UserApi { private readonly _userService = inject(UserService); @Get('/') @ReturnType(User) // Single entity public getUser(req: Request): Promise { // req.user populated by UserAuth class return this._userService.getUser(req.user); } @Delete('/') @ReturnType(PrimitiveReferences.Boolean) // Primitive types public deleteUser(req: Request): Promise { // req.user populated by UserAuth class await this._userService.deleteUser(req.user); return true; } } ``` -------------------------------- ### Use EncryptedRecordDao to Save and Retrieve Encrypted Values Source: https://context7_llms This example illustrates the usage of `EncryptedRecordDao` for persisting and retrieving encrypted data. It shows how to save a secret value, obtain an `encryptedValueId` for linking, and then use this ID to retrieve the original decrypted value. The DAO relies on `CryptoService` for encryption/decryption. ```JavaScript const encryptedRecordDao = inject(EncryptedRecordDao); // Encrypted data is stored in the database, // and the link is established via `encryptedValueId`. const encryptedValueId = await encryptedRecordDao.saveEncryptedValue( 'secret_data', transaction, ); // To retrieve the decrypted value, use `encryptedValueId`. const decryptedValue = await encryptedRecordDao.getDecryptedValue( { encryptedValueId }, transaction, ); ``` -------------------------------- ### TypeScript: Implementing Service Layer Error Handling with Custom Errors Source: https://context7_llms Provides an example of implementing robust error handling at the service layer by defining custom error classes that extend `AbstractError`. It demonstrates how to check for business logic conditions, such as duplicate emails or insufficient permissions, and throw specific, descriptive errors that can be caught and handled by the application. ```typescript import { AbstractError } from '@myre/engine/core'; // Define specific error classes extending AbstractError export class UserEmailAlreadyExistsError extends AbstractError { constructor(email: string) { super(50001, { en: 'A user with this email already exists', fr: 'Un utilisateur avec cet email existe déjà', }, { email }); } } export class InsufficientPermissionsError extends AbstractError { constructor(userId: number, organizationId: number) { super(50002, { en: 'Insufficient permissions to create users in this organization', fr: 'Permissions insuffisantes pour créer des utilisateurs dans cette organisation', }, { userId, organizationId }); } } @Service() export class UserService { private readonly _userDao = inject(UserDao); public async createUser( scope: { loggedUser: User; customer: Customer; organization: Organization; }, data: CreateUserEntity ): Promise { // Use scope object for all DAO operations const existingUser = await this._userDao.findByEmail(scope, data.email); if (existingUser) { throw new UserEmailAlreadyExistsError(data.email); } // Validate permissions using scope entities if (!scope.loggedUser.canCreateUsersIn(scope.organization)) { throw new InsufficientPermissionsError( scope.loggedUser.id, scope.organization.id ); } return await this._userDao.createUser(scope, data); } } ``` -------------------------------- ### TypeScript: Orchestrating Multiple DAO Operations with @Transactional Source: https://context7_llms Illustrates how to manage multiple Data Access Object (DAO) operations within a single transaction using the `@Transactional()` decorator. The example shows a `UserService` method that orchestrates the creation of a user and their profile, ensuring both operations commit or rollback together, and how to extend scope objects for subsequent operations. ```typescript import { Service, inject } from '@myre/engine/api'; import { Transactional } from '@myre/seq/core'; @Service() export class UserService { private readonly _userDao = inject(UserDao); private readonly _profileDao = inject(ProfileDao); @Transactional() public async createUserWithProfile( scope: { loggedUser: User; customer: Customer; organization: Organization; }, userData: CreateUserEntity, profileData: CreateProfileEntity, transaction?: Transaction // automatically added by @Transactional() ): Promise { // Both operations use the same transaction and scope object const user = await this._userDao.createUser(scope, userData, transaction!); // Extend scope with newly created user for profile creation const profileScope = { ...scope, targetUser: user }; await this._profileDao.createProfile(profileScope, profileData, transaction!); return user; } } ``` -------------------------------- ### Extracting Optional Query Parameters with @Query() in TypeScript Source: https://context7_llms Illustrates how to use the @Query() decorator to extract optional individual query parameters from the request. It shows examples for string, number, and enum types, and how to process comma-separated string values into an array of numbers. ```typescript @Controller('/users') export class UsersApi { private readonly _userService = inject(UserService); @Get('/') @ReturnType(User, { isArray: true }) public getUsers( req: Request, @Query('search', String) search?: string, @Query('limit', Number) limit?: number, @Query('status', String) status?: UserStatus ): Promise { return this._userService.getUsers(req.customer, { search, limit, status }); } @Get('/filtered') @ReturnType(User, { isArray: true }) public getFilteredUsers( req: Request, @Query('roleIds', String) roleIdsString?: string, // "1,2,3" @Query('active', Boolean) active?: boolean ): Promise { const roleIds = roleIdsString ? roleIdsString.split(',').map(Number) : undefined; return this._userService.getFilteredUsers(req.customer, { roleIds, active }); } } ``` -------------------------------- ### Specify Return Types for SDK Generation with @ReturnType Decorator (TypeScript) Source: https://context7_llms Illustrates the basic usage of the `@ReturnType()` decorator to define the expected return type for API endpoints, which is crucial for SDK generation. This decorator is mandatory for all endpoints and includes examples for returning an array of entities, a single entity, a primitive boolean, and a string. ```TypeScript @Controller('/users') export class UsersApi { private readonly _userService = inject(UserService); // Array return @Get('/') @ReturnType(User, { isArray: true }) public getUsers(req: Request): Promise { // implementation } } @Controller('/:userId') @Auth(UserAuth) export class UserApi { private readonly _userService = inject(UserService); // Single entity return @Get('/') @ReturnType(User) public getUser(req: Request): Promise { // implementation } // Primitive return @Delete('/') @ReturnType(PrimitiveReferences.Boolean) public deleteUser(req: Request): Promise { // implementation } // String return @Get('/avatar-url') @ReturnType(PrimitiveReferences.String) public getUserAvatarUrl(req: Request): Promise { // implementation } } ``` -------------------------------- ### Implementing Custom Business Logic Validation and Error Handling in TypeScript Services Source: https://context7_llms Provides an example of defining and utilizing custom error classes, extending AbstractError, for business logic validation within a TypeScript service. It demonstrates how to throw specific, localized errors based on business rules, such as invalid email domains or restricted user types, within a transactional context. ```TypeScript import { Service, inject } from '@myre/engine/api'; import { Transactional } from '@myre/seq/core'; import { AbstractError } from '@myre/engine/core'; // Define specific validation error classes export class InvalidEmailDomainError extends AbstractError { constructor(email: string) { super(50005, { en: 'Email domain not allowed', fr: 'Domaine email non autorisé' }, { email }); } } export class AdminUsersNotAllowedError extends AbstractError { constructor(customerId: number) { super(50006, { en: 'Admin users not allowed for this customer', fr: 'Utilisateurs admin non autorisés pour ce client' }, { customerId }); } } @Service() export class UserService { private readonly _userDao = inject(UserDao); @Transactional() public async createUser( scope: { loggedUser: User; customer: Customer; organization: Organization; }, data: CreateUser, transaction?: Transaction // automatically added by @Transactional() ): Promise { await this._checkBusinessRules(scope, data); return this._userDao.createUser(scope, data, transaction!); } private async _checkBusinessRules( scope: { loggedUser: User; customer: Customer; organization: Organization; }, data: CreateUser ): Promise { // Custom business validation using scope entities if (data.email.endsWith('@competitor.com')) { throw new InvalidEmailDomainError(data.email); } if (data.name.toLowerCase().includes('admin') && !scope.customer.allowAdminUsers) { throw new AdminUsersNotAllowedError(scope.customer.id); } // Additional validation using other scope entities if (!scope.loggedUser.canCreateUsersIn(scope.organization)) { throw new InsufficientPermissionsError( scope.loggedUser.id, scope.organization.id ); } } } ``` -------------------------------- ### Extending IncrementerDao Abstract Class Source: https://context7_llms To leverage the `IncrementerDao` for managing column increments, it is necessary to extend this abstract class. This example demonstrates extending it with `IncrementModel` (representing the counter table with linked entity, counter columns, and a version for optimistic lock) and `CounterKeys` (representing all keys that can be incremented). ```TypeScript class InstanceIncrementDao extends IncrementerDao< IncrementModel, CounterKeys > { public getIncrementer( _transaction: Transaction, ): IncrementerFunction { [...] } } ``` -------------------------------- ### TypeScript Entity Validation Anti-Patterns and Best Practices Source: https://context7_llms Illustrates common anti-patterns in TypeScript entity validation using decorators like @IsObject, @IsOptional, and generic type validators. Provides corrected examples demonstrating the use of @IsInstance for nested entities, combining @IsOptional with specific validators, and employing precise validation types like @IsSmallInt, @IsString(length), and @IsDecimal for better data integrity and efficiency. ```TypeScript // ❌ Don't use @IsObject for nested entities export class BadUserEntity extends BaseValidatorClass { @IsObject() public address: any; // Loses type safety } // ✅ Use @IsInstance for nested entities export class GoodUserEntity extends BaseValidatorClass { @IsInstance(AddressEntity) public address: AddressEntity; // Type-safe } // ❌ Don't use @IsOptional alone export class BadOptionalEntity extends BaseValidatorClass { @IsOptional() public name?: string; // Missing main validator } // ✅ Combine @IsOptional with other validators export class GoodOptionalEntity extends BaseValidatorClass { @IsString() @IsOptional() public name?: string; // Properly validated } // ❌ Don't use generic types when specific ones exist export class InEfficientEntity extends BaseValidatorClass { @IsInteger() // Too broad for small numbers public priority: number; @IsText() // No length limit when one could be set public code: string; @IsNumeric() // Less precise than @IsDecimal public amount: number; } // ✅ Use specific validation types export class EfficientEntity extends BaseValidatorClass { @IsSmallInt() // Specific for small numbers public priority: number; @IsString(50) // Appropriate length limit public code: string; @IsDecimal([10, 2]) // Precise decimal specification public amount: number; } ``` -------------------------------- ### Bootstrapping Myre Engine Applications Source: https://context7_llms Details the process of initializing a Myre Engine application using the bootstrap method. It demonstrates configuring the application with port, controllers (including nested and scoped routes), and providers. ```TypeScript import { bootstrap } from '@myre/engine/api'; import { type Bootstrap } from '@myre/engine/api'; // Bootstrap configuration example with customer-scoped structure const config: Bootstrap = { port: 4242, controllers: [ { route: '/customers/:customerId', controller: CustomerApi, // Has @Auth(CustomerAuth) children: [ UsersApi, // Nested under customer scope OrdersApi, // Nested under customer scope { route: '/users/:userId', controller: UserApi // Individual user operations } ] }, PublicApi // Public endpoints without customer scope ], providers: [ UserService, CustomerService, { provide: Token, useValue: 'VALUE' } ] }; // Start the application const server = await bootstrap(config); ``` -------------------------------- ### Handle Required Query Parameters with @QueryRequired() in Myre Engine Source: https://context7_llms The @QueryRequired() parameter decorator is used to extract mandatory query parameters from the request URL. This example demonstrates its application for a GET endpoint that requires a 'format' string parameter, ensuring necessary data is provided for an export operation and enforcing data integrity. ```TypeScript import { Controller, Get, QueryRequired, ReturnType, inject, PrimitiveReferences } from '@myre/engine/api'; import { Request } from 'express'; @Controller('/users') export class UserApi { private readonly _userService = inject(UserService); @Get('/export') @ReturnType(PrimitiveReferences.String) public exportUsers( req: Request, @QueryRequired('format', String) format: string ): Promise { return this._userService.exportUsers(format); } } ``` -------------------------------- ### Advanced Dependency Injection Provider Patterns in Myre Engine Source: https://context7_llms Illustrates advanced dependency injection techniques, including the use of InjectionToken for custom providers, useValue for static values, and useFactory with deps for dynamic dependency resolution during application bootstrap. ```TypeScript import { Service, inject, InjectionToken } from '@myre/engine/api'; export const envToken = new InjectionToken('env'); export const configToken = new InjectionToken('config'); @Service() export class MyService1 { private _config = inject(configToken); } @Service() export class MyService2 { constructor( private _myService1: MyService1 ) { } } // Provider registration in bootstrap providers: [ MyService1, MyService2, { provide: envToken, useValue: process.env.NODE_ENV, }, { provide: configToken, useFactory: (env: string) => generateConfFromEnv(env), deps: [envToken] }, ] ``` -------------------------------- ### Specify Endpoint Return Type with @ReturnType() in Myre Engine Source: https://context7_llms The @ReturnType() decorator is mandatory for all API endpoints and specifies the expected return type, which is crucial for SDK generation and proper type inference. This example shows how to define an array of User objects as the return type for a GET endpoint, ensuring consistent API contracts. ```TypeScript import { Controller, Get, ReturnType, inject } from '@myre/engine/api'; @Controller('/users') export class UserApi { private readonly _userService = inject(UserService); @Get('/') @ReturnType(User, { isArray: true }) public getUsers(): Promise { return this._userService.getUsers(); } } ``` -------------------------------- ### Basic Dependency Injection with Myre Engine Source: https://context7_llms Demonstrates fundamental dependency injection using @Service() and inject() decorators to manage service dependencies like UserDao within a UserService class. ```TypeScript import { Service, inject } from '@myre/engine/api'; @Service() export class UserService { private readonly _userDao = inject(UserDao); public async getUsers(): Promise { return this._userDao.findAll(); } } ``` -------------------------------- ### Configure Backend with EncryptedRecordModel Import Source: https://context7_llms This snippet demonstrates how to import the necessary service models, including `EncryptedRecordModel`, into a backend application using `getServiceModels`. It highlights the importance of reflecting any model updates in the database for proper functionality. ```JavaScript const models = [ ...getServiceModels(), ]; ``` -------------------------------- ### Usage Notes for Key Validation Decorators Source: https://context7_llms Detailed usage notes for specific validation decorators, explaining their behavior, parameters, and common pitfalls or special considerations. ```APIDOC @IsOptional(): Notes: Must be combined with other validators. Use {nullable: false} to disallow null values while allowing undefined. @IsDecimal(): Notes: Use [precision, scale] format for financial amounts, e.g., @IsDecimal([10, 2]). @IsInstance(): Notes: For single nested entities. Use picker function for dynamic type selection, e.g., @IsInstance([TypeA, TypeB], picker). @IsInstanceArray(): Notes: For arrays of nested entities. Supports same picker pattern as @IsInstance(). @SwaggerExtraInfo(): Notes: Add 'x-enumName' for enums, 'examples' for sample values. @HasAdditionalProperties(): Notes: Class decorator that allows additional properties in Swagger schema. Apply to the class, not individual properties. @IsString(): Notes: Default maximum length is 255 characters. Use @IsText() for unlimited text. @IsDateOnlyUnrestricted(): Notes: Allows dates outside the DWH date range (1900-2199), unlike @IsDateOnly() which enforces DWH date range restrictions. BasePeriod: Notes: Base class for entities needing optional startDate and endDate fields with built-in validation. ``` -------------------------------- ### Updating Logical Database References Example Source: https://context7_llms Example TypeScript code demonstrating the usage of `updateLogicalReferences` to replace references to an old entity ID with a new one across tables in a specified schema. This method is used when the reference is not a foreign key but is marked with a specific external reference comment. ```TypeScript await updateLogicalReferences( Schema.Public, Schema.Entity, 'entity', targetEntity.id, [sourceEntity.id], ) ``` -------------------------------- ### Authentication and Authorization Decorators Source: https://context7_llms Overview of @Auth() and @Rights() decorators provided by the Myre Engine framework for securing endpoints. Discusses key concepts like Auth Classes for parameter validation and Rights-Based Authorization for fine-grained control. ```APIDOC @Auth(): Purpose: Validates parameters and populates request objects (e.g., req.user, req.customer). Usage: Applied to endpoints for authentication. @Rights(): Purpose: Provides fine-grained permission control. Usage: Applied to endpoints for authorization based on rights. Key Concepts: Auth Classes: Validate parameters and populate request objects. Rights-Based Authorization: Utilizes @Rights() for permission control. Security-First Design: Emphasizes avoiding direct parameter access in controllers. ``` -------------------------------- ### Managing Multiple Dependencies with Myre Engine Injection Source: https://context7_llms Shows how to inject multiple dependencies (UserDao, EmailService, LogService) into a single service (UserService) to orchestrate complex operations like user creation, email sending, and logging. ```TypeScript import { Service, inject } from '@myre/engine/api'; @Service() export class UserService { private readonly _userDao = inject(UserDao); private readonly _emailService = inject(EmailService); private readonly _logService = inject(LogService); public async createUser(data: CreateUser): Promise { const user = await this._userDao.createUser(data); await this._emailService.sendWelcomeEmail(user.email); this._logService.logUserCreation(user.id); return user; } } ``` -------------------------------- ### Describing Controllers for Swagger with @ApiDescription() in TypeScript Source: https://context7_llms Illustrates the use of the @ApiDescription() decorator to add a general description to a controller, which is then used for generating comprehensive Swagger API documentation, improving API discoverability. ```typescript @Controller('/users') @ApiDescription({ description: 'User management operations' }) export class UserApi { // endpoints } ``` -------------------------------- ### Import API Decorators from @myre/engine/api Source: https://context7_llms This section outlines the standard way to import various API decorators and related utilities from the `@myre/engine/api` package, along with other necessary modules like `@myre/seq/core` and `@myre/engine/models` for building API services. ```typescript import { Controller, Get, Post, Put, Delete, Patch, Body, ReturnType, Auth, Rights, Version, ApiDescription, ApiOperation, Query, QueryRequired, Param, File, inject, Service, Scope, SCOPES, PrimitiveReferences } from '@myre/engine/api'; import { Transactional } from '@myre/seq/core'; import { PermissionRight } from '@myre/engine/models'; import { PermissionResource } from '@myre/engine/models/am'; ``` -------------------------------- ### Injecting Dependencies with inject() Function Source: https://context7_llms Illustrates how to use the inject() function for dependency injection within service classes, showing how to inject DAOs and other services. ```TypeScript @Service() export class UserService { private readonly _userDao = inject(UserDao); private readonly _emailService = inject(EmailService); public async createUser(data: CreateUser): Promise { const user = await this._userDao.createUser(data); await this._emailService.sendWelcomeEmail(user.email); return user; } } ``` -------------------------------- ### Framework's Automatic SDK Generation Overview Source: https://context7_llms Describes the framework's capability to automatically generate TypeScript SDKs. This process is driven by the @ReturnType() and @Body() decorators used in API endpoint definitions, simplifying client-side integration. ```APIDOC The framework automatically generates TypeScript SDKs based on `@ReturnType()` and `@Body()` decorators. For complete SDK information, see the [main API documentation](/docs/api/#sdk-generation). ``` -------------------------------- ### Define Array of Nested Entities with @IsInstanceArray in TypeScript Source: https://context7_llms This example shows how to define an entity, `UserEntity`, that contains an array of `ContactEntity` objects. The `@IsInstanceArray()` decorator is used to validate each element within the `contacts` array, ensuring they are all instances of `ContactEntity`. ```TypeScript export class ContactEntity extends BaseValidatorClass { @IsString() public type: string; @IsString() public value: string; } export class UserEntity extends BaseValidatorClass { @IsInteger() @Min(1) public id: number; @IsInstanceArray(ContactEntity) public contacts: readonly ContactEntity[]; } ``` -------------------------------- ### Define Complex Nested Entity Structures in TypeScript Source: https://context7_llms This snippet provides an example of a `BudgetPlanEntity` with multiple arrays of nested entities, specifically `PropertyNameEntity` and `CorporateNameEntity`. It demonstrates how to handle complex data structures where an entity contains several collections of other entities. ```TypeScript export class PropertyNameEntity extends BaseValidatorClass { @IsString() public name: string; } export class CorporateNameEntity extends BaseValidatorClass { @IsString() public name: string; } export class BudgetPlanEntity extends BaseValidatorClass { @IsInteger() @Min(1) public id: number; @IsString() public name: string; @IsInstanceArray(PropertyNameEntity) public propertyNames: readonly PropertyNameEntity[]; @IsInstanceArray(CorporateNameEntity) public corporateNames: readonly CorporateNameEntity[]; } ``` -------------------------------- ### Key Integration Rules for Framework API Endpoints Source: https://context7_llms Outlines the fundamental best practices for integrating with the framework's API. It emphasizes the mandatory use of @ReturnType() for all endpoints, @Body() for endpoints with request bodies, and the exclusive use of individual @Query() parameters instead of validation entities. ```APIDOC Key Integration Rules: 1. Always use `@ReturnType()` - Mandatory for all endpoints 2. Always use `@Body()` - Mandatory for endpoints with request bodies 3. Use individual `@Query()` parameters - Not validation entities for query parameters ``` -------------------------------- ### Describing Controllers with @ApiDescription Source: https://context7_llms Demonstrates how to use the @ApiDescription decorator to add a description to a controller for Swagger documentation. This helps in organizing and clarifying the purpose of API endpoints. ```TypeScript import { Controller, ApiDescription } from '@myre/engine/api'; @Controller('/users') @ApiDescription({ description: 'User management operations' }) export class UserApi { // endpoints } ``` -------------------------------- ### Implement Translation Entities for Localized Fields in TypeScript Source: https://context7_llms This example demonstrates how to use `TranslationEntity` for localized fields like `name` and an optional `description` within a `CategoryEntity`. This pattern allows for robust multi-language support by encapsulating translated content within a dedicated entity. ```TypeScript import { TranslationEntity } from '@myre/engine/models'; export class CategoryEntity extends BaseValidatorClass { @IsInteger() @Min(1) public id: number; @IsInstance(TranslationEntity) public name: TranslationEntity; @IsInstance(TranslationEntity) @IsOptional() public description?: TranslationEntity; } ```