@elsikora/nestjs-crud-automator
Version:
A library for automating the creation of CRUD operations in NestJS.
206 lines (202 loc) • 12.9 kB
JavaScript
;
require('../../../../enum/decorator/api/action.enum.js');
require('../../../../enum/decorator/api/authentication-type.enum.js');
require('../../../../enum/decorator/api/controller/get-list/query/filter/missing-behavior.enum.js');
var paginationMode_enum = require('../../../../enum/decorator/api/controller/get-list/query/pagination-mode.enum.js');
require('../../../../enum/decorator/api/controller/get-list/query/unlisted-fields.enum.js');
require('../../../../enum/decorator/api/controller/relation-reference-shape.enum.js');
require('../../../../enum/decorator/api/controller/request/target.enum.js');
require('../../../../enum/decorator/api/controller/request/transformer-type.enum.js');
require('../../../../enum/decorator/api/controller/response-target.enum.js');
var dtoType_enum = require('../../../../enum/decorator/api/dto-type.enum.js');
require('../../../../enum/decorator/api/function/context-storage-kind.enum.js');
require('../../../../enum/decorator/api/function/subscriber-transaction-expectation.enum.js');
require('../../../../enum/decorator/api/function/transaction/event-status.enum.js');
require('../../../../enum/decorator/api/function/transaction/failure-stage.enum.js');
require('../../../../enum/decorator/api/function/transaction/mode.enum.js');
require('../../../../enum/decorator/api/function/transaction/outcome.enum.js');
require('../../../../enum/decorator/api/function/transaction/owner-kind.enum.js');
require('../../../../enum/decorator/api/function/transaction/trace-type.enum.js');
require('../../../../enum/decorator/api/function/type.enum.js');
require('../../../../enum/decorator/api/on-type.enum.js');
require('../../../../enum/decorator/api/property/data-type.enum.js');
require('../../../../enum/decorator/api/property/date/identifier.enum.js');
require('../../../../enum/decorator/api/property/date/type.enum.js');
require('../../../../enum/decorator/api/property/desribe-type.enum.js');
require('../../../../enum/decorator/api/property/number-type.enum.js');
require('../../../../enum/decorator/api/property/string-type.enum.js');
require('../../../../enum/decorator/api/route/subscriber-authorization-expectation.enum.js');
var type_enum = require('../../../../enum/decorator/api/route/type.enum.js');
var getPaginationMode_utility = require('../get-list/query/get-pagination-mode.utility.js');
var assertPlan_utility = require('../identity/assert-plan.utility.js');
var assertPlan_utility$1 = require('../read/assert-plan.utility.js');
require('@nestjs/common');
var camelCaseString_utility = require('../../../camel-case-string.utility.js');
require('../../../../constant/utility/dto/constant.js');
var exception_utility = require('../../../error/exception.utility.js');
var core_utility = require('../../../dto/generate/core.utility.js');
require('@nestjs/swagger');
require('../../../../external/tslib/tslib.es6.js');
require('../../../../class/utility/dto/exception/details/foreign-key-violation.class.js');
require('../../../../class/utility/dto/exception/details/unique-violation.class.js');
require('../../../../enum/utility/manual-dto-property-metadata-decorator.enum.js');
require('class-transformer');
require('class-validator');
require('lodash/random.js');
require('@nestjs/swagger/dist/constants.js');
require('../../../../validator/must-match-one-of-schemas.validator.js');
require('../../../../constant/interface/api/property/default-string-format.constant.js');
require('../../../../validator/is-regular-expression.validator.js');
require('node:crypto');
require('../../../../enum/utility/exception-details-type.enum.js');
require('../../../../enum/filter/operand.enum.js');
require('../../../../enum/filter/operation.enum.js');
require('../../../../enum/filter/order-direction.enum.js');
var cursorResponse_utility = require('../../../dto/generate/get-list/cursor-response.utility.js');
require('../../../../constant/decorator/api/function.constant.js');
require('../../../../class/metadata-storage.class.js');
require('typeorm');
var response_utility = require('../../../dto/generate/get-list/response.utility.js');
require('reflect-metadata');
require('../../../../validator/all-or-none-of-listed-properties.validator.js');
var identityReadParameters_utility = require('../../../dto/generate/identity-read-parameters.utility.js');
var readParameters_utility = require('../../../dto/generate/read-parameters.utility.js');
const getListItemResponseDtoCache = new Map();
const getListCursorItemResponseDtoCache = new WeakMap();
const getListCursorItemResponseDtoNameOwnerCache = new WeakMap();
/**
* Resolves a DTO class for a generated controller route.
* Prefers an explicitly configured DTO and falls back to auto-generation.
* @param {IApiControllerProperties<E>} properties - Controller configuration
* @param {IApiEntity<E>} entity - Entity metadata
* @param {R} method - Route type
* @param {EApiDtoType} dtoType - DTO kind to resolve
* @param {TApiControllerPropertiesRoute<E, R>} routeConfig - Route-specific configuration
* @param {IApiControllerGetListQueryPlan} [queryPlan] - Route-scoped plan for dynamic GET_LIST QUERY DTO generation.
* @returns {Type<unknown> | undefined} -The resolved DTO class or undefined if no DTO is configured
* @template E - Entity type
* @template R - Route type
*/
function ApiControllerGetDto(properties, entity, method, dtoType, routeConfig, queryPlan) {
assertPlan_utility$1.ApiControllerReadPlanAssert(routeConfig);
return ApiControllerGetDtoWithReadPlan(properties, entity, method, dtoType, routeConfig, queryPlan);
}
/**
* Resolves a route DTO while applying an internal compiled read plan.
* @template E - Entity type
* @template R - Route type
* @param {IApiControllerProperties<E>} properties - Controller properties
* @param {IApiEntity<E>} entity - Entity metadata
* @param {R} method - Route method
* @param {EApiDtoType} dtoType - DTO kind to resolve
* @param {TApiControllerPropertiesRoute<E, R>} routeConfig - Route-specific configuration
* @param {IApiControllerGetListQueryPlan} [queryPlan] - Route-scoped GET_LIST QUERY plan.
* @param {IApiControllerReadPlan} [readPlan] - Internal route-scoped PARAMETERS plan.
* @param {IApiControllerIdentityPlan} [identityPlan] - Internal GET identity alias plan.
* @returns {Type<unknown> | undefined} Resolved DTO class or undefined.
*/
function ApiControllerGetDtoWithReadPlan(properties, entity, method, dtoType, routeConfig, queryPlan, readPlan, identityPlan) {
assertPlan_utility.ApiControllerIdentityPlanAssert(routeConfig, identityPlan);
if (dtoType === dtoType_enum.EApiDtoType.PARAMETERS) {
assertPlan_utility$1.ApiControllerReadPlanAssert(routeConfig, readPlan);
}
const configuredDto = routeConfig.dto?.[dtoType];
if (configuredDto) {
if (method === type_enum.EApiRouteType.GET_LIST && dtoType === dtoType_enum.EApiDtoType.RESPONSE && isGetListResponseDtoConfig(configuredDto)) {
return getGetListItemResponseDto(properties.entity, entity, configuredDto, method, dtoType, queryPlan);
}
return configuredDto;
}
if (dtoType === dtoType_enum.EApiDtoType.PARAMETERS) {
if (identityPlan) {
return identityReadParameters_utility.DtoGenerateIdentityReadParameters(entity, identityPlan, readPlan, routeConfig.autoDto?.[dtoType], routeConfig.security?.authentication?.guard);
}
if (readPlan) {
return readParameters_utility.DtoGenerateReadParameters(entity, method, readPlan, routeConfig.autoDto?.[dtoType], routeConfig.security?.authentication?.guard);
}
}
const isCursorGetListResponse = method === type_enum.EApiRouteType.GET_LIST && dtoType === dtoType_enum.EApiDtoType.RESPONSE && getPaginationMode_utility.ApiControllerGetListQueryGetPaginationMode(queryPlan) === paginationMode_enum.EApiControllerGetListQueryPaginationMode.CURSOR;
const effectiveQueryPlan = method === type_enum.EApiRouteType.GET_LIST && (dtoType === dtoType_enum.EApiDtoType.QUERY || isCursorGetListResponse) ? queryPlan : undefined;
return core_utility.DtoGenerate(properties.entity, entity, method, dtoType, routeConfig.autoDto?.[dtoType], routeConfig.security?.authentication?.guard, effectiveQueryPlan);
}
/**
* Builds a stable generated wrapper class name for GET_LIST custom item response DTOs.
* @param {IApiEntity<E>} entity - Entity metadata used for the resource name.
* @param {IApiControllerPropertiesRouteGetListResponseDtoConfig} config - Custom item response DTO config.
* @param {EApiRouteType} method - Current route type.
* @param {EApiDtoType} dtoType - Current DTO type.
* @returns {string} Generated wrapper DTO class name.
* @template E - Entity type.
*/
function buildGetListItemResponseDtoName(entity, config, method, dtoType) {
return config.name ?? `${entity.name ?? "UnknownResource"}${camelCaseString_utility.CamelCaseString(method)}${camelCaseString_utility.CamelCaseString(dtoType)}${config.itemType.name}`;
}
/**
* Generates or returns a cached list wrapper around a configured custom item response DTO.
* @param {ObjectLiteral} resourceClass - Entity class used for wrapper metadata.
* @param {IApiEntity<E>} entity - Entity metadata used for naming.
* @param {IApiControllerPropertiesRouteGetListResponseDtoConfig} config - Custom item response DTO config.
* @param {EApiRouteType} method - Current route type.
* @param {EApiDtoType} dtoType - Current DTO type.
* @param {IApiControllerGetListQueryPlan} [queryPlan] - Compiled pagination plan selecting the page or cursor wrapper.
* @returns {Type<unknown>} Generated list wrapper DTO class.
* @template E - Entity type.
*/
function getGetListItemResponseDto(resourceClass, entity, config, method, dtoType, queryPlan) {
const isCursor = getPaginationMode_utility.ApiControllerGetListQueryGetPaginationMode(queryPlan) === paginationMode_enum.EApiControllerGetListQueryPaginationMode.CURSOR;
const defaultName = buildGetListItemResponseDtoName(entity, config, method, dtoType);
if (!isCursor) {
const cacheKey = `${entity.name ?? "UnknownResource"}_${config.itemType.name}_${defaultName}`;
const cached = getListItemResponseDtoCache.get(cacheKey);
if (cached) {
return cached;
}
// @ts-ignore The existing list wrapper generator accepts the entity constructor at runtime.
const dto = response_utility.DtoGenerateGetListResponse(resourceClass, config.itemType, defaultName);
getListItemResponseDtoCache.set(cacheKey, dto);
return dto;
}
const name = config.name ?? `${defaultName}Cursor`;
const cacheKey = `${entity.name ?? "UnknownResource"}_${name}_cursor`;
const nameOwnerKey = `${entity.name ?? "UnknownResource"}_${name}`;
let nameOwnerCache = getListCursorItemResponseDtoNameOwnerCache.get(resourceClass);
if (!nameOwnerCache) {
nameOwnerCache = new Map();
getListCursorItemResponseDtoNameOwnerCache.set(resourceClass, nameOwnerCache);
}
const currentNameOwner = nameOwnerCache.get(nameOwnerKey);
const hasPageConflict = [...getListItemResponseDtoCache.values()].some((dto) => dto.name === name);
if (hasPageConflict || (currentNameOwner && currentNameOwner !== config.itemType)) {
throw exception_utility.ErrorException(`GET_LIST item response DTO wrapper name "${name}" is already used by another item constructor or pagination mode; configure a unique response DTO name`);
}
nameOwnerCache.set(nameOwnerKey, config.itemType);
let resourceCache = getListCursorItemResponseDtoCache.get(resourceClass);
if (!resourceCache) {
resourceCache = new WeakMap();
getListCursorItemResponseDtoCache.set(resourceClass, resourceCache);
}
let itemCache = resourceCache.get(config.itemType);
if (!itemCache) {
itemCache = new Map();
resourceCache.set(config.itemType, itemCache);
}
const cached = itemCache.get(cacheKey);
if (cached) {
return cached;
}
// @ts-ignore The existing list wrapper generators accept the entity constructor at runtime.
const dto = cursorResponse_utility.DtoGenerateGetListCursorResponse(resourceClass, config.itemType, name);
itemCache.set(cacheKey, dto);
return dto;
}
/**
* Returns whether a route response DTO config describes a custom GET_LIST item DTO.
* @param {IApiControllerPropertiesRouteGetListResponseDtoConfig | Type<unknown>} value - Configured response DTO value.
* @returns {boolean} Whether the value is the item DTO config shape.
*/
function isGetListResponseDtoConfig(value) {
return typeof value === "object" && "itemType" in value && typeof value.itemType === "function";
}
exports.ApiControllerGetDto = ApiControllerGetDto;
exports.ApiControllerGetDtoWithReadPlan = ApiControllerGetDtoWithReadPlan;
//# sourceMappingURL=dto.utility.js.map