crud-automator
DevelopmentDesign, audit, document, refactor, and implement NestJS CRUD Automator resources using @elsikora/nestjs-crud-automator. Use when working with ApiController, ApiService, ApiFunction, ApiFunctionCustom, ApiRouteCustom, ApiMethod, ApiPropertyDescribe, ApiPropertyCopy, manual DTOs, autoDto, GET_LIST response item DTOs, transformers, validators, relation loading, subscribers, authorization policies, HOOKS/IAM, transaction scopes, Swagger contracts, or replacing hand-written NestJS CRUD patterns with native Crud Automator features.
QUICK START
How to use this skill
Bring this guide into your coding agent with a prompt tailored to the tool you use.
- Open your project in Codex.
- Copy and paste the prompt below.
- Review files and risks before approving any action.
Prompt to paste
Inspect the Agent Skill at https://github.com/ElsiKora/NestJS-Crud-Automator/blob/HEAD/ai/crud-automator/SKILL.md and all supporting files. Report provenance, permissions, scripts, dependencies, and security risks. Propose an exact installation into .agents/skills/crud-automator, but wait for my approval before writing files or running scripts.
Copying this prompt does not install or run the skill. Review third-party files before use.
Crud Automator
Source Priority
Use local source as the contract:
src/interface/**,src/type/**, and exported barrels define public API shape.test/unit/**andtest/e2e/**show supported behavior.docs/**andREADME.mdexplain behavior, but may drift and must be checked against source.
Default Workflow
- Inspect the existing entity, service, controller, subscriber, policy, and DTO configuration.
- Prefer native Crud Automator primitives before adding custom controllers, mappers, facades, or wrappers.
- Verify route config against current interfaces before copying examples.
- Validate Swagger, DTO shape, relation loading, subscriber firing, authorization decisions, and transaction behavior after meaningful changes.
Current Contract Reminders
@ApiController()applies Nest@Controller()internally; usepath.routes: {}is valid and still generates default CRUD routes; omitted route entries do not disable routes.- Generated controller routes are
CREATE,GET,GET_LIST,UPDATE(PUT /:id),PARTIAL_UPDATE(PATCH /:id), andDELETE. GET_MANYis service/function/subscriber-only, not a generated HTTP route.- Route controls live under
generation:generation.isEnabled,generation.shouldWriteToController, andgeneration.decorators. - Route security lives under
security.authenticationandsecurity.authorization. authentication.typeis the principal category (USER,ADMIN,ACCOUNT,MERCHANT, or project string), not the bearer/security scheme.- Route-level Swagger security schemes use
authentication.securityRequirements; one object is an AND group and multiple objects are OR alternatives. - Request config is target keyed with
EApiControllerRequestTarget.BODY,PARAMETERS, andQUERY. - Response config is target keyed with
EApiControllerResponseTarget.RESPONSE. - OpenAPI response headers live directly under
response.headers, not underEApiControllerResponseTarget.RESPONSE. autoDtois validators-only. Field exposure, requiredness, filters, guards, and response visibility belong toApiPropertyDescribe({ properties }).- Manual
dtoandautoDtoroute branches are mutually exclusive. ApiPropertyDescribeobject metadata usesdataType; manualApiPropertyObjectusestype.ApiPropertyDescriberelation metadata does not currently accept array options.GetDefaultStringFormatProperties(format)provides canonical defaults for supported string formats.
Function And Transaction Model
- Service/function
createandupdatereceiveDeepPartial<E>directly, not{ body }. - Service/function
get,getList, andgetManyreceive TypeORM options. - Generated service/context
deleteisPromise<void>; direct decorator internals have a known return-shape inconsistency, so document and test the intended surface before changing it. @ApiFunctionCustom({ action, entity, transaction })is for custom service commands that need function lifecycle, subscribers, and transaction context.@ApiFunctionStep({ entity, transaction })is for internal service helper methods that need transaction context but are not standalone actions; direct calls are valid when the selected transaction mode permits.- Function steps do not create subscriber hooks, route metadata, Swagger metadata, or authorization action identities; do not model them as custom actions.
@ApiService({ entity, functions })can configure transaction modes for generated CRUD functions keyed byEApiFunctionType.CREATE,UPDATE,DELETE,GET,GET_LIST, andGET_MANY; omitted entries default toSUPPORTS, andCUSTOMbelongs to@ApiFunctionCustom.- Function execution transaction modes use
EApiFunctionTransactionModewithtransaction.mode; subscriber requirements useEApiFunctionSubscriberTransactionExpectationwithtransaction.expectation. - Inside decorated service execution, use
this.getApiFunctionContext()foroperations,repository,eventManager, andgetRepository. - Inside
@ApiFunctionStep, usethis.getApiFunctionStepContext()forrepository,eventManager, andgetRepository; it intentionally omitsoperations. ApiFunctionTransactionScope.runWithDataSource()andrunWithEntityManager()provide external transaction scope; CRUDoperationsreject without a decorated service context.
Route Runtime Model
- Use
@ApiRouteCustomfor custom controller routes that need runtime behavior: transformers, validators, relation handling, subscribers, authorization result transforms, or serialization. - Use
@ApiFunctionCustom<Entity>(...)and@ApiRouteCustom<Entity>(...); response types belong on method return types and response metadata, not decorator generic parameters. - Use
@ApiMethodas the low-level metadata/Nest/Swagger/security/throttling composer. @ApiMethodmetadata lives undermetadata.resource,metadata.route,metadata.response,metadata.security, andmetadata.throttling.- Securable custom methods need method-level authorization mode metadata.
- Custom route response relation reload requires
controller.serviceto extendApiServiceBaseand response items to have anid. - For
@ApiRouteCustom, request relation loading hydrates only the method@Body()argument; custom route before-hook auth, headers, IP, metadata, and runtime properties live incontext.DATA, notcontext.result.
Relation Model
- Request relation config:
relations.request.referenceandrelations.request.load. - Request load config uses
relations.request.load.include, optionalrelations.request.load.relationLoadStrategy, and optionalrelations.request.load.servicesoverrides. relations.request.load.includeis the single source of truth for direct request relations to hydrate. Omitted service keys use${relationName}Service.- Response relation config:
relations.response.referenceandrelations.response.load.includewith optionalrelationLoadStrategy. - HTTP generated relation filters use explicit one-level paths such as
author.id[...]andauthor.username[...]; top-levelauthor[...]is not generated or transformed. - Generated relation filters skip relation fields and object fields on the related entity.
- For nested request or response relations, use TypeORM relation object maps in
load.include. - Nested request include objects are only passed to the direct relation service as TypeORM
relations; nested request references are not recursively hydrated.
Subscriber Model
- Import
ApiSubscriberModule, register subscriber classes as Nest providers, and mark observed controllers/services with@ApiControllerObservable()/@ApiServiceObservable(). - Route subscribers receive route-shaped results such as
{ body, parameters, query, headers, ip, authenticationRequest }in before hooks. - Custom route subscribers receive
{ body?, parameters?, query? }incontext.result; read auth/header/IP data fromcontext.DATA. - Route subscriber authorization expectations are declared on
@ApiRouteSubscriber({ authorization: { expectation } }); they are type-only. Use matching class/context generics withEApiRouteSubscriberAuthorizationExpectation.REQUIREDonly when the route contract guaranteesauthenticationRequest.authorizationDecision. - Function subscribers receive service payloads directly; do not use
context.result.bodyin function subscribers. - Function subscriber transaction expectations are declared on
@ApiFunctionSubscriber({ transaction: { expectation } }); they are not inferred from service/function config. Use matching class/context generics forREQUIREDorMANDATORYsocontext.DATA.eventManagernarrows toEntityManager. - Custom hooks are
onBeforeCustom,onAfterCustom,onBeforeErrorCustom, andonAfterErrorCustom. - Higher
priorityruns earlier; returned non-undefinedhook results flow to later subscribers.
Authorization Model
- Use
EApiAuthorizationMode.HOOKSplusApiAuthorizationPolicyfor code-first app rules. - Use IAM mode for policy documents, principal resolution, document sources, attachment sources, and boundaries.
- Register
@ApiAuthorizationPolicy()classes as Nest providers. - IAM policy document
Resourcevalues match literally or with wildcards;{id}placeholders belong inresourceDefinition.resourcePath. - Use
ApiAuthorizationCacheInvalidationServiceafter backing authorization data changes;clearAll()clears policy, IAM attachment/document, and hook permission caches.
Verification Checklist
- Generated Swagger matches request and response contracts.
- DTO fields are scoped correctly for body/query/parameters/response.
- GET_LIST uses the intended response mode: full wrapper DTO or
{ itemType, name? }. - Route generation, security, request/response targets, relations, and DTO config type-check.
- Subscribers fire on the route/function path being exercised.
- Authorization metadata, policy documents, resource definitions, and cache invalidation match runtime behavior.
- No wrapper helper was added where a native primitive is already clear.
Additional Resources
- For detailed source-aligned guidance, see reference.md.
- For copyable patterns, see examples.md.
- For common failure modes, see pitfalls.md.