@things-factory/shell 10.0.0-zeta.8 → 10.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/client/entries/public/home.js +1 -1
  2. package/client/themes/app-theme.css +8 -24
  3. package/client/themes/calendar-theme.css +0 -7
  4. package/client/themes/grist-theme.css +13 -37
  5. package/client/themes/layout-theme.css +3 -23
  6. package/client/themes/report-theme.css +0 -9
  7. package/client/themes/theme-base.css +30 -0
  8. package/client/themes/tooltip-theme.css +0 -4
  9. package/dist-server/bootstrap-hooks.d.ts +51 -0
  10. package/dist-server/bootstrap-hooks.js +39 -0
  11. package/dist-server/bootstrap-hooks.js.map +1 -0
  12. package/dist-server/index.d.ts +1 -0
  13. package/dist-server/index.js +1 -0
  14. package/dist-server/index.js.map +1 -1
  15. package/dist-server/initializers/database.js +4 -1
  16. package/dist-server/initializers/database.js.map +1 -1
  17. package/dist-server/migrations/1785369600000-IndexDomainOwner.d.ts +5 -0
  18. package/dist-server/migrations/1785369600000-IndexDomainOwner.js +49 -0
  19. package/dist-server/migrations/1785369600000-IndexDomainOwner.js.map +1 -0
  20. package/dist-server/server-dev.js +13 -10
  21. package/dist-server/server-dev.js.map +1 -1
  22. package/dist-server/server.js +12 -8
  23. package/dist-server/server.js.map +1 -1
  24. package/dist-server/service/domain/domain-mutation.js +3 -2
  25. package/dist-server/service/domain/domain-mutation.js.map +1 -1
  26. package/dist-server/service/domain/domain.js +12 -1
  27. package/dist-server/service/domain/domain.js.map +1 -1
  28. package/dist-server/service/env-var/env-var-mutation.js +6 -1
  29. package/dist-server/service/env-var/env-var-mutation.js.map +1 -1
  30. package/dist-server/tsconfig.tsbuildinfo +1 -1
  31. package/dist-server/typeorm/get-data-encryption-key.js +11 -1
  32. package/dist-server/typeorm/get-data-encryption-key.js.map +1 -1
  33. package/dist-server/utils/apply-domain-filter.d.ts +17 -0
  34. package/dist-server/utils/apply-domain-filter.js +30 -0
  35. package/dist-server/utils/apply-domain-filter.js.map +1 -0
  36. package/dist-server/utils/condition-builder.js +15 -7
  37. package/dist-server/utils/condition-builder.js.map +1 -1
  38. package/dist-server/utils/get-query-builder-from-list-params.d.ts +39 -9
  39. package/dist-server/utils/get-query-builder-from-list-params.js +83 -40
  40. package/dist-server/utils/get-query-builder-from-list-params.js.map +1 -1
  41. package/dist-server/utils/index.d.ts +1 -0
  42. package/dist-server/utils/index.js +1 -0
  43. package/dist-server/utils/index.js.map +1 -1
  44. package/dist-server/utils/list-params-converter.js +8 -6
  45. package/dist-server/utils/list-params-converter.js.map +1 -1
  46. package/dist-server/utils/list-query-builder.js +2 -14
  47. package/dist-server/utils/list-query-builder.js.map +1 -1
  48. package/jest.config.js +5 -0
  49. package/package.json +12 -12
  50. package/tests/domain-owner-index.test.ts +121 -0
  51. package/tests/env-var-tenant-isolation.test.ts +118 -0
  52. package/tests/get-query-builder-features.test.ts +229 -0
  53. package/tests/list-param-operators.test.ts +87 -0
  54. package/tests/manifest-contract.test.ts +38 -0
  55. package/client/store.ts +0 -15
@@ -1 +1 @@
1
- {"version":3,"file":"get-query-builder-from-list-params.js","sourceRoot":"","sources":["../../server/utils/get-query-builder-from-list-params.ts"],"names":[],"mappings":"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","sourcesContent":["import { Brackets, EntityMetadata, Repository, SelectQueryBuilder, WhereExpressionBuilder } from 'typeorm'\nimport { RelationMetadata } from 'typeorm/metadata/RelationMetadata.js'\nimport { Filter, Sorting, Pagination, ListParam, InheritedValueType } from '../service/common-types/list-param.js'\nimport { Domain } from '../service/domain/domain.js'\n\n/**\n * Creates a TypeORM SelectQueryBuilder based on the provided parameters.\n *\n * @param options - An object containing the query building options.\n * @param options.repository - The TypeORM repository for database operations.\n * @param options.params - The ListParam object containing filters, sortings, and pagination.\n * @param [options.domain] - Optional domain object for applying domain-specific filters.\n * @param [options.alias] - The alias to be used in the SQL queries.\n * @param [options.searchables] - List of columns that are searchable.\n * @param [options.filtersMap] - Mapping of filter names to their corresponding columns or relation columns.\n * @returns {SelectQueryBuilder<Type>} - The constructed SelectQueryBuilder instance.\n */\nexport function getQueryBuilderFromListParams<Type>(options: {\n repository: Repository<Type>\n params: ListParam\n domain?: Domain\n alias?: string\n searchables?: string[]\n filtersMap?: { [name: string]: { columnName: string; relationColumn?: string } }\n}): SelectQueryBuilder<Type> {\n const { repository, params, domain, alias, searchables, filtersMap = {} } = options\n const { inherited = InheritedValueType.None } = params || {}\n\n const selectQueryBuilder = repository.createQueryBuilder(alias)\n const entityAlias = selectQueryBuilder.alias\n\n // Apply filters to the query\n const columnFilters =\n params.filters?.filter(filter => {\n if (filter.operator === 'search') {\n return false\n }\n if (filter.operator.toLowerCase().includes('like') && (!searchables || !searchables.includes(filter.name))) {\n console.warn('\"searchables\" setting is required for LIKE searches to avoid heavy database load', filter.name)\n return false\n }\n return true\n }) || []\n\n const searchFilters =\n searchables instanceof Array\n ? params.filters?.filter(filter => {\n if (filter.operator !== 'search') {\n return false\n }\n if (!searchables.includes(filter.name)) {\n console.warn(\n '\"searchables\" setting is required for LIKE searches to avoid heavy database load',\n filter.name\n )\n return false\n }\n return true\n }) || []\n : []\n\n const pagination = params.pagination\n const sortings = params.sortings\n const metadata = repository.metadata\n\n // Apply column filters\n if (columnFilters.length > 0) {\n columnFilters.forEach(filter => {\n addCondition(metadata, selectQueryBuilder, selectQueryBuilder, filter, filtersMap, true)\n })\n }\n\n // Apply search filters\n if (searchFilters.length > 0) {\n selectQueryBuilder.andWhere(\n new Brackets(qb => {\n searchFilters.forEach(filter => {\n addCondition(metadata, selectQueryBuilder, qb, filter, filtersMap, false)\n })\n })\n )\n }\n\n // Apply domain filters\n if (domain) {\n if (!inherited || inherited === InheritedValueType.None) {\n selectQueryBuilder.andWhere(`${entityAlias}.domain = :domain`, { domain: domain.id })\n } else if (inherited === InheritedValueType.Include) {\n selectQueryBuilder.andWhere(`${entityAlias}.domain IN (:...domains)`, {\n domains: [domain.id, domain.parentId].filter(Boolean)\n })\n } else if (inherited === InheritedValueType.Only) {\n selectQueryBuilder.andWhere(`${entityAlias}.domain = :domain`, { domain: domain.parentId || 'Impossible' })\n } else {\n selectQueryBuilder.andWhere(`${entityAlias}.domain = :domain`, { domain: 'Impossible' })\n }\n }\n\n // Apply pagination\n addPagination(selectQueryBuilder, pagination)\n\n // Apply sorting\n if (sortings && sortings.length > 0) {\n addSorting(selectQueryBuilder, sortings, entityAlias, filtersMap, metadata)\n }\n\n return selectQueryBuilder\n}\n\n/**\n * Adds pagination to the SelectQueryBuilder based on the provided Pagination object.\n *\n * @param selectQueryBuilder - The SelectQueryBuilder to which pagination should be applied.\n * @param pagination - The Pagination object containing page and limit information.\n */\nfunction addPagination<T>(selectQueryBuilder: SelectQueryBuilder<T>, pagination?: Pagination) {\n if (pagination) {\n const { page, limit } = pagination\n if (page && limit && page > 0 && limit > 0) {\n selectQueryBuilder.skip(limit * (page - 1)).take(limit)\n } else if (limit && limit > 0) {\n selectQueryBuilder.take(limit)\n }\n }\n}\n\n/**\n * Adds a filtering condition to the SelectQueryBuilder based on the provided filter and mapping options.\n *\n * @param metadata - The EntityMetadata of the TypeORM entity.\n * @param selectQueryBuilder - The SelectQueryBuilder to which the condition will be added.\n * @param whereExpressionBuilder - The WhereExpressionBuilder to construct the where clause.\n * @param filter - The Filter object containing the filter criteria.\n * @param filtersMap - A mapping of filter names to column names and relation column names.\n * @param andCondition - A flag indicating whether to use \"AND\" or \"OR\" for combining conditions.\n */\nfunction addCondition<T>(\n metadata: EntityMetadata,\n selectQueryBuilder: SelectQueryBuilder<T>,\n whereExpressionBuilder: WhereExpressionBuilder,\n filter: Filter,\n filtersMap: { [name: string]: { columnName: string; relationColumn?: string } } = {},\n andCondition: boolean\n): void {\n const { name, operator, value } = filter\n var entityAlias = selectQueryBuilder.alias\n\n var { relationColumn, columnName } = filtersMap[name] || {}\n /*\n 1. relationColumn과 columnName이 지정된 경우 \n - relation inverse 테이블에서, columnName을 찾는다.\n 2. relationColumn만 지정된 경우는 없어야 한다.\n - 이 경우 columnName 은 'name' 이라고 판단한다.\n 3. columnName이 지정된 경우.\n - 이 경우는 columnName 만 적용한다.\n */\n if (relationColumn) {\n const columns = relationColumn.split('.')\n var entityMetadata: EntityMetadata\n var relation: RelationMetadata\n\n for (const rcolumn of columns) {\n if (relation) {\n const { propertyName } = relationColumnMeta\n const property = `${entityAlias}.${propertyName}`\n\n entityAlias = `${entityAlias}-${entityMetadata.tableName}-for-${columnName || 'name'}` as string\n\n if (andCondition) {\n selectQueryBuilder.innerJoin(property, entityAlias)\n } else {\n selectQueryBuilder.leftJoin(property, entityAlias)\n }\n } else {\n entityMetadata = metadata\n }\n\n var relationColumnMeta = entityMetadata.columns.find(column => column.propertyName === rcolumn)\n if (!relationColumnMeta) {\n console.warn(`relationColumn \"${relationColumn}\" in filtersMap for \"${name}\" is not a relation column`)\n return\n }\n\n relation = relationColumnMeta.relationMetadata\n entityMetadata = relation.inverseEntityMetadata\n }\n\n var columnMeta = entityMetadata.columns.find(column => column.propertyName === (columnName || 'name'))\n if (!columnMeta) {\n console.warn(`columnName \"${columnName}\" in filtersMap for \"${name}\" is not a column`)\n return\n }\n } else {\n var columnMeta = metadata.columns.find(column => column.propertyName === (columnName || name))\n if (!columnMeta) {\n /* relationId 에 대한 필터링은 해당 컬럼값 자체의 비교로 한다. */\n var relationIdMeta = metadata.relationIds.find(relationId => relationId.propertyName === (columnName || name))\n if (relationIdMeta) {\n columnMeta = relationIdMeta.relation.joinColumns[0]\n } else {\n columnName\n ? console.warn(`columnName \"${columnName}\" in filtersMap for \"${name}\" is not a column`)\n : console.warn(`name \"${name}\" is not a column`)\n }\n } else {\n var relation = columnMeta.relationMetadata\n }\n\n if (relation) {\n /* filterMap에 의해서 relationColumn 이 지정되지 않았더라도, name 또는 columnName의 column이 relation인 경우에는\n - 조건절 구성을 위한 타겟필드명은 'name' 으로만 한정된다.\n */\n var relationColumnMeta = columnMeta\n var entityMetadata = relation.inverseEntityMetadata\n columnMeta = entityMetadata.columns.find(column => column.propertyName === 'name')\n if (!columnMeta) {\n console.warn(`relation column \"${columnName || name}\" does not have \"name\" column`)\n return\n }\n }\n }\n\n const dbNameForColumn = columnMeta.databaseName\n const alias = relationColumnMeta ? `${name}-filter` : entityAlias\n\n /* relation columne인 경우 name을 alias로 사용한다. */\n const field = `${alias}.${dbNameForColumn}`\n\n var { clause, parameters } = getClauseAndParameters(field, name, operator, value)\n\n if (relationColumnMeta) {\n const { propertyName } = relationColumnMeta\n const property = `${entityAlias}.${propertyName}`\n if (andCondition) {\n selectQueryBuilder.innerJoin(property, alias, clause, parameters)\n } else {\n selectQueryBuilder.leftJoin(property, alias)\n whereExpressionBuilder.orWhere(clause, parameters)\n }\n } else {\n andCondition\n ? whereExpressionBuilder.andWhere(clause, parameters)\n : whereExpressionBuilder.orWhere(clause, parameters)\n }\n}\n\n/**\n * Adds sorting to the SelectQueryBuilder based on the provided Sorting objects.\n *\n * @param selectQueryBuilder - The SelectQueryBuilder to which sorting should be applied.\n * @param sortings - An array of Sorting objects defining the sort order.\n * @param entityAlias - The alias of the entity in the query.\n * @param filtersMap - A mapping of filter names to column names and relation column names.\n * @param metadata - The EntityMetadata of the TypeORM entity.\n */\nfunction addSorting<T>(\n selectQueryBuilder: SelectQueryBuilder<T>,\n sortings: Sorting[],\n entityAlias: string,\n filtersMap: { [name: string]: { columnName: string; relationColumn?: string } },\n metadata: EntityMetadata\n) {\n sortings.forEach((sorting, index) => {\n const sortField = determineSortField(sorting.name, entityAlias, filtersMap, selectQueryBuilder, metadata)\n if (index === 0) {\n selectQueryBuilder.orderBy(sortField, sorting.desc ? 'DESC' : 'ASC')\n } else {\n selectQueryBuilder.addOrderBy(sortField, sorting.desc ? 'DESC' : 'ASC')\n }\n })\n}\n\n/**\n * Determines the sorting field for a given sorting name, considering possible relation columns.\n *\n * @param sortingName - The name of the field to sort by.\n * @param entityAlias - The alias of the entity in the query.\n * @param filtersMap - A mapping of filter names to column names and relation column names.\n * @param selectQueryBuilder - The SelectQueryBuilder instance to apply sorting to.\n * @param metadata - The EntityMetadata of the TypeORM entity.\n * @returns {string} - The fully qualified sorting field.\n */\nfunction determineSortField<T>(\n sortingName: string,\n entityAlias: string,\n filtersMap: { [name: string]: { columnName: string; relationColumn?: string } },\n selectQueryBuilder: SelectQueryBuilder<T>,\n metadata: EntityMetadata\n): string {\n const filter = filtersMap[sortingName]\n\n if (!filter) {\n return sortingName.split('.').length > 1 ? sortingName : `${entityAlias}.${sortingName}`\n }\n\n const { columnName, relationColumn } = filter\n\n if (relationColumn) {\n const relationAlias = applyJoins(\n selectQueryBuilder,\n entityAlias,\n relationColumn,\n metadata,\n 'leftJoin',\n columnName || sortingName,\n true\n )\n return `${relationAlias}.${columnName}`\n } else {\n return `${entityAlias}.${columnName}`\n }\n}\n\n/**\n * Applies the necessary joins to the SelectQueryBuilder based on the relation column.\n *\n * @param selectQueryBuilder - The SelectQueryBuilder where the joins will be applied.\n * @param entityAlias - The current alias of the entity in the query.\n * @param relationColumn - The dot-notated string representing the relation chain (e.g., \"user.profile.address\").\n * @param metadata - The EntityMetadata of the entity.\n * @param joinType - The type of join to use (\"innerJoin\" or \"leftJoin\").\n * @param columnName - The name of the column used for filtering or sorting, default to 'name'.\n * @param selectField - Whether to include the field in the SELECT clause.\n * @returns {string} - The alias to be used for the final field in the relation chain.\n */\nfunction applyJoins<T>(\n selectQueryBuilder: SelectQueryBuilder<T>,\n entityAlias: string,\n relationColumn: string,\n metadata: EntityMetadata,\n joinType: 'innerJoin' | 'leftJoin' = 'leftJoin',\n columnName: string = 'name',\n selectField: boolean = false\n): string {\n const columns = relationColumn.split('.')\n let currentAlias = entityAlias\n let currentMetadata = metadata\n\n for (const column of columns) {\n const relation = currentMetadata.relations.find(rel => rel.propertyName === column)\n\n if (!relation) {\n throw new Error(`Relation not found for column: ${column}`)\n }\n\n const nextAlias = `${currentAlias}_${relation.inverseEntityMetadata.tableName}_for_${columnName}`\n\n if (!selectQueryBuilder.expressionMap.aliases.some(alias => alias.name === nextAlias)) {\n selectQueryBuilder[joinType](`${currentAlias}.${column}`, nextAlias)\n }\n if (selectField && columns.at(-1) == column /* 최종 alias만 추가 */) {\n selectQueryBuilder.addSelect(`${nextAlias}.${columnName}`, `${nextAlias}_${columnName}`)\n }\n\n currentAlias = nextAlias\n currentMetadata = relation.inverseEntityMetadata\n }\n\n return currentAlias\n}\n\n/**\n * Generates the SQL clause and parameters based on the provided filter.\n *\n * @param field - The database field to filter on.\n * @param name - The name of the filter.\n * @param operator - The operator to use in the filter.\n * @param value - The value to filter with.\n * @returns An object containing the SQL clause and the parameters.\n */\nfunction getClauseAndParameters(\n field: string,\n name: string,\n operator: string,\n value: any\n): { clause: string; parameters: { [key: string]: any } } {\n const values = value instanceof Array ? value : [value]\n let clause = ''\n let parameters: { [key: string]: any } = {}\n\n switch (operator) {\n case 'eq':\n clause = `${field} = :${name}`\n parameters = { [name]: value }\n break\n case 'like':\n clause = `${field} LIKE :${name}`\n parameters = { [name]: `%${value}%` }\n break\n case 'search':\n case 'i_like':\n clause = `LOWER(${field}) LIKE :${name}`\n parameters = { [name]: `%${String(value).toLowerCase()}%` }\n break\n case 'nlike':\n clause = `${field} NOT LIKE :${name}`\n parameters = { [name]: `%${value}%` }\n break\n case 'i_nlike':\n clause = `LOWER(${field}) NOT LIKE :${name}`\n parameters = { [name]: `%${String(value).toLowerCase()}%` }\n break\n case 'lt':\n clause = `${field} < :${name}`\n parameters = { [name]: value }\n break\n case 'gt':\n clause = `${field} > :${name}`\n parameters = { [name]: value }\n break\n case 'lte':\n clause = `${field} <= :${name}`\n parameters = { [name]: value }\n break\n case 'gte':\n clause = `${field} >= :${name}`\n parameters = { [name]: value }\n break\n case 'noteq':\n clause = `${field} != :${name}`\n parameters = { [name]: value }\n break\n case 'in':\n clause = `${field} IN (:...${name})`\n parameters = { [name]: values }\n break\n case 'notin':\n clause = `${field} NOT IN (:...${name})`\n parameters = { [name]: values }\n break\n case 'notin_with_null':\n clause = `${field} IS NULL OR ${field} NOT IN (:...${name})`\n parameters = { [name]: values }\n break\n case 'is_null':\n clause = `${field} IS NULL`\n break\n case 'is_not_null':\n clause = `${field} IS NOT NULL`\n break\n case 'is_false':\n clause = `${field} IS FALSE`\n break\n case 'is_true':\n clause = `${field} IS TRUE`\n break\n case 'is_not_false':\n clause = `${field} IS NOT FALSE`\n break\n case 'is_not_true':\n clause = `${field} IS NOT TRUE`\n break\n case 'is_present':\n clause = `${field} IS PRESENT`\n break\n case 'is_blank':\n clause = `${field} IS BLANK`\n break\n case 'is_empty_num_id':\n clause = `${field} IS EMPTY NUMERIC ID`\n break\n case 'between':\n clause = `${field} BETWEEN :${name}_1 AND :${name}_2`\n parameters = { [`${name}_1`]: values[0], [`${name}_2`]: values[1] }\n break\n }\n\n return { clause, parameters }\n}\n"]}
1
+ {"version":3,"file":"get-query-builder-from-list-params.js","sourceRoot":"","sources":["../../server/utils/get-query-builder-from-list-params.ts"],"names":[],"mappings":"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","sourcesContent":["import { Brackets, EntityMetadata, Repository, SelectQueryBuilder, WhereExpressionBuilder } from 'typeorm'\nimport { RelationMetadata } from 'typeorm/metadata/RelationMetadata.js'\nimport { Filter, Sorting, Pagination, ListParam, InheritedValueType } from '../service/common-types/list-param.js'\nimport { Domain } from '../service/domain/domain.js'\nimport { applyDomainInheritanceFilter } from './apply-domain-filter.js'\n\n/**\n * `search` 연산자의 매칭 방식.\n * - contains(기본): `%v%` — 어디든 포함(유연하나 인덱스 미활용).\n * - startsWith: `v%` — 접두 일치(인덱스 활용 가능 → 대용량에서 빠름).\n * - exact: `v` — 정확 일치(대소문자 무시).\n */\nexport type SearchMode = 'contains' | 'startsWith' | 'exact'\n\n/**\n * Builds a TypeORM SelectQueryBuilder from a generic ListParam (filters, search, sortings,\n * pagination) plus optional multi-tenant domain scoping. Returns the builder so callers can\n * further chain joins/select/where before executing (e.g. getMany / getManyAndCount).\n *\n * Supported filter operators (`Filter.operator`):\n * eq, noteq, like, nlike, i_like, i_nlike, search, lt, gt, lte, gte,\n * in, notin, notin_with_null, between,\n * is_null, is_not_null, is_true, is_false, is_not_true, is_not_false,\n * is_present, is_blank, is_empty_num_id.\n * An unknown operator throws a clear, actionable error.\n *\n * Behavior notes:\n * - `search` uses case-insensitive substring match (`LOWER(col) LIKE %v%`) and requires the column\n * to be listed in `searchables`.\n * - `like`/`i_like` filters are IGNORED (with a console.warn) unless the column is in `searchables`,\n * to avoid unindexed full-table scans.\n * - Boolean operators are emitted as parameter-bound comparisons (portable across all supported DBs).\n * - Domain scoping is applied only when `domain` is provided, honoring `params.inherited`\n * (None = own domain, Include = own + parent, Only = parent).\n * - Pagination uses skip/take; with joins this triggers TypeORM's two-query strategy for correctness.\n * - Unknown filter columns / operators / relations throw a clear, actionable error (fail-fast).\n *\n * @param options.repository TypeORM repository (or a tx-scoped repository) to build from.\n * @param options.params ListParam: `{ filters, sortings, pagination, inherited }`.\n * @param [options.domain] Optional current domain `{ id, parentId }` for tenant scoping.\n * @param [options.alias] Optional entity alias (defaults to the entity name).\n * @param [options.searchables] Columns eligible for `search`/`like` filtering.\n * @param [options.filtersMap] Maps a filter/sort name to a column or relation column, e.g.\n * `{ ownerName: { columnName: 'name', relationColumn: 'owner' } }`.\n * @param [options.searchMode] `search` matching mode: 'contains'(default) / 'startsWith' / 'exact'.\n * 'startsWith' emits `v%` (prefix) which can use an index on large tables.\n * @returns {SelectQueryBuilder<Type>} The constructed SelectQueryBuilder (not yet executed).\n */\nexport function getQueryBuilderFromListParams<Type>(options: {\n repository: Repository<Type>\n params: ListParam\n domain?: Domain\n alias?: string\n searchables?: string[]\n filtersMap?: { [name: string]: { columnName: string; relationColumn?: string } }\n searchMode?: SearchMode\n}): SelectQueryBuilder<Type> {\n const { repository, params, domain, alias, searchables, filtersMap = {}, searchMode = 'contains' } = options\n const { inherited = InheritedValueType.None } = params || {}\n\n const selectQueryBuilder = repository.createQueryBuilder(alias)\n const entityAlias = selectQueryBuilder.alias\n\n // Apply filters to the query\n const columnFilters =\n params.filters?.filter(filter => {\n if (filter.operator === 'search') {\n return false\n }\n if (filter.operator.toLowerCase().includes('like') && (!searchables || !searchables.includes(filter.name))) {\n console.warn('\"searchables\" setting is required for LIKE searches to avoid heavy database load', filter.name)\n return false\n }\n return true\n }) || []\n\n const searchFilters =\n searchables instanceof Array\n ? params.filters?.filter(filter => {\n if (filter.operator !== 'search') {\n return false\n }\n if (!searchables.includes(filter.name)) {\n console.warn(\n '\"searchables\" setting is required for LIKE searches to avoid heavy database load',\n filter.name\n )\n return false\n }\n return true\n }) || []\n : []\n\n const pagination = params.pagination\n const sortings = params.sortings\n const metadata = repository.metadata\n\n // Apply column filters\n if (columnFilters.length > 0) {\n columnFilters.forEach(filter => {\n addCondition(metadata, selectQueryBuilder, selectQueryBuilder, filter, filtersMap, true, searchMode)\n })\n }\n\n // Apply search filters\n if (searchFilters.length > 0) {\n selectQueryBuilder.andWhere(\n new Brackets(qb => {\n searchFilters.forEach(filter => {\n addCondition(metadata, selectQueryBuilder, qb, filter, filtersMap, false, searchMode)\n })\n })\n )\n }\n\n // Apply domain filters\n if (domain) {\n applyDomainInheritanceFilter(selectQueryBuilder, entityAlias, domain, inherited)\n }\n\n // Apply pagination\n addPagination(selectQueryBuilder, pagination)\n\n // Apply sorting\n if (sortings && sortings.length > 0) {\n addSorting(selectQueryBuilder, sortings, entityAlias, filtersMap, metadata)\n }\n\n return selectQueryBuilder\n}\n\n/**\n * Adds pagination to the SelectQueryBuilder based on the provided Pagination object.\n *\n * @param selectQueryBuilder - The SelectQueryBuilder to which pagination should be applied.\n * @param pagination - The Pagination object containing page and limit information.\n */\nfunction addPagination<T>(selectQueryBuilder: SelectQueryBuilder<T>, pagination?: Pagination) {\n if (pagination) {\n const { page, limit } = pagination\n if (page && limit && page > 0 && limit > 0) {\n selectQueryBuilder.skip(limit * (page - 1)).take(limit)\n } else if (limit && limit > 0) {\n selectQueryBuilder.take(limit)\n }\n }\n}\n\n/**\n * Adds a filtering condition to the SelectQueryBuilder based on the provided filter and mapping options.\n *\n * @param metadata - The EntityMetadata of the TypeORM entity.\n * @param selectQueryBuilder - The SelectQueryBuilder to which the condition will be added.\n * @param whereExpressionBuilder - The WhereExpressionBuilder to construct the where clause.\n * @param filter - The Filter object containing the filter criteria.\n * @param filtersMap - A mapping of filter names to column names and relation column names.\n * @param andCondition - A flag indicating whether to use \"AND\" or \"OR\" for combining conditions.\n */\nfunction addCondition<T>(\n metadata: EntityMetadata,\n selectQueryBuilder: SelectQueryBuilder<T>,\n whereExpressionBuilder: WhereExpressionBuilder,\n filter: Filter,\n filtersMap: { [name: string]: { columnName: string; relationColumn?: string } } = {},\n andCondition: boolean,\n searchMode: SearchMode = 'contains'\n): void {\n const { name, operator, value } = filter\n var entityAlias = selectQueryBuilder.alias\n\n var { relationColumn, columnName } = filtersMap[name] || {}\n /*\n 1. relationColumn과 columnName이 지정된 경우 \n - relation inverse 테이블에서, columnName을 찾는다.\n 2. relationColumn만 지정된 경우는 없어야 한다.\n - 이 경우 columnName 은 'name' 이라고 판단한다.\n 3. columnName이 지정된 경우.\n - 이 경우는 columnName 만 적용한다.\n */\n if (relationColumn) {\n const columns = relationColumn.split('.')\n var entityMetadata: EntityMetadata\n var relation: RelationMetadata\n\n for (const rcolumn of columns) {\n if (relation) {\n const { propertyName } = relationColumnMeta\n const property = `${entityAlias}.${propertyName}`\n\n entityAlias = `${entityAlias}-${entityMetadata.tableName}-for-${columnName || 'name'}` as string\n\n if (andCondition) {\n selectQueryBuilder.innerJoin(property, entityAlias)\n } else {\n selectQueryBuilder.leftJoin(property, entityAlias)\n }\n } else {\n entityMetadata = metadata\n }\n\n var relationColumnMeta = entityMetadata.columns.find(column => column.propertyName === rcolumn)\n if (!relationColumnMeta) {\n console.warn(`relationColumn \"${relationColumn}\" in filtersMap for \"${name}\" is not a relation column`)\n return\n }\n\n relation = relationColumnMeta.relationMetadata\n entityMetadata = relation.inverseEntityMetadata\n }\n\n var columnMeta = entityMetadata.columns.find(column => column.propertyName === (columnName || 'name'))\n if (!columnMeta) {\n console.warn(`columnName \"${columnName}\" in filtersMap for \"${name}\" is not a column`)\n return\n }\n } else {\n var columnMeta = metadata.columns.find(column => column.propertyName === (columnName || name))\n if (!columnMeta) {\n /* relationId 에 대한 필터링은 해당 컬럼값 자체의 비교로 한다. */\n var relationIdMeta = metadata.relationIds.find(relationId => relationId.propertyName === (columnName || name))\n if (relationIdMeta) {\n columnMeta = relationIdMeta.relation.joinColumns[0]\n } else {\n /* 미지의 컬럼: 이전엔 warn 후 흘러가 columnMeta.databaseName 에서 불투명 TypeError 로 크래시했다.\n 원인을 바로 알 수 있도록 명확·실행가능한 오류를 던진다(fail-fast). */\n const target = columnName || name\n const available = metadata.columns.map(column => column.propertyName).join(', ')\n throw new Error(\n `[getQueryBuilderFromListParams] unknown filter column \"${target}\" on entity \"${metadata.name}\". ` +\n `Add a filtersMap entry for \"${name}\", or use one of: ${available}`\n )\n }\n } else {\n var relation = columnMeta.relationMetadata\n }\n\n if (relation) {\n /* filterMap에 의해서 relationColumn 이 지정되지 않았더라도, name 또는 columnName의 column이 relation인 경우에는\n - 조건절 구성을 위한 타겟필드명은 'name' 으로만 한정된다.\n */\n var relationColumnMeta = columnMeta\n var entityMetadata = relation.inverseEntityMetadata\n columnMeta = entityMetadata.columns.find(column => column.propertyName === 'name')\n if (!columnMeta) {\n console.warn(`relation column \"${columnName || name}\" does not have \"name\" column`)\n return\n }\n }\n }\n\n const dbNameForColumn = columnMeta.databaseName\n const alias = relationColumnMeta ? `${name}-filter` : entityAlias\n\n /* relation columne인 경우 name을 alias로 사용한다. */\n const field = `${alias}.${dbNameForColumn}`\n\n var { clause, parameters } = getClauseAndParameters(field, name, operator, value, searchMode)\n\n if (relationColumnMeta) {\n const { propertyName } = relationColumnMeta\n const property = `${entityAlias}.${propertyName}`\n if (andCondition) {\n selectQueryBuilder.innerJoin(property, alias, clause, parameters)\n } else {\n selectQueryBuilder.leftJoin(property, alias)\n whereExpressionBuilder.orWhere(clause, parameters)\n }\n } else {\n andCondition\n ? whereExpressionBuilder.andWhere(clause, parameters)\n : whereExpressionBuilder.orWhere(clause, parameters)\n }\n}\n\n/**\n * Adds sorting to the SelectQueryBuilder based on the provided Sorting objects.\n *\n * @param selectQueryBuilder - The SelectQueryBuilder to which sorting should be applied.\n * @param sortings - An array of Sorting objects defining the sort order.\n * @param entityAlias - The alias of the entity in the query.\n * @param filtersMap - A mapping of filter names to column names and relation column names.\n * @param metadata - The EntityMetadata of the TypeORM entity.\n */\nfunction addSorting<T>(\n selectQueryBuilder: SelectQueryBuilder<T>,\n sortings: Sorting[],\n entityAlias: string,\n filtersMap: { [name: string]: { columnName: string; relationColumn?: string } },\n metadata: EntityMetadata\n) {\n sortings.forEach((sorting, index) => {\n const sortField = determineSortField(sorting.name, entityAlias, filtersMap, selectQueryBuilder, metadata)\n if (index === 0) {\n selectQueryBuilder.orderBy(sortField, sorting.desc ? 'DESC' : 'ASC')\n } else {\n selectQueryBuilder.addOrderBy(sortField, sorting.desc ? 'DESC' : 'ASC')\n }\n })\n}\n\n/**\n * Determines the sorting field for a given sorting name, considering possible relation columns.\n *\n * @param sortingName - The name of the field to sort by.\n * @param entityAlias - The alias of the entity in the query.\n * @param filtersMap - A mapping of filter names to column names and relation column names.\n * @param selectQueryBuilder - The SelectQueryBuilder instance to apply sorting to.\n * @param metadata - The EntityMetadata of the TypeORM entity.\n * @returns {string} - The fully qualified sorting field.\n */\nfunction determineSortField<T>(\n sortingName: string,\n entityAlias: string,\n filtersMap: { [name: string]: { columnName: string; relationColumn?: string } },\n selectQueryBuilder: SelectQueryBuilder<T>,\n metadata: EntityMetadata\n): string {\n const filter = filtersMap[sortingName]\n\n if (!filter) {\n return sortingName.split('.').length > 1 ? sortingName : `${entityAlias}.${sortingName}`\n }\n\n const { columnName, relationColumn } = filter\n\n if (relationColumn) {\n const relationAlias = applyJoins(\n selectQueryBuilder,\n entityAlias,\n relationColumn,\n metadata,\n 'leftJoin',\n columnName || sortingName,\n true\n )\n return `${relationAlias}.${columnName}`\n } else {\n return `${entityAlias}.${columnName}`\n }\n}\n\n/**\n * Applies the necessary joins to the SelectQueryBuilder based on the relation column.\n *\n * @param selectQueryBuilder - The SelectQueryBuilder where the joins will be applied.\n * @param entityAlias - The current alias of the entity in the query.\n * @param relationColumn - The dot-notated string representing the relation chain (e.g., \"user.profile.address\").\n * @param metadata - The EntityMetadata of the entity.\n * @param joinType - The type of join to use (\"innerJoin\" or \"leftJoin\").\n * @param columnName - The name of the column used for filtering or sorting, default to 'name'.\n * @param selectField - Whether to include the field in the SELECT clause.\n * @returns {string} - The alias to be used for the final field in the relation chain.\n */\nfunction applyJoins<T>(\n selectQueryBuilder: SelectQueryBuilder<T>,\n entityAlias: string,\n relationColumn: string,\n metadata: EntityMetadata,\n joinType: 'innerJoin' | 'leftJoin' = 'leftJoin',\n columnName: string = 'name',\n selectField: boolean = false\n): string {\n const columns = relationColumn.split('.')\n let currentAlias = entityAlias\n let currentMetadata = metadata\n\n for (const column of columns) {\n const relation = currentMetadata.relations.find(rel => rel.propertyName === column)\n\n if (!relation) {\n const available = currentMetadata.relations.map(rel => rel.propertyName).join(', ')\n throw new Error(\n `[getQueryBuilderFromListParams] relation \"${column}\" not found on entity \"${currentMetadata.name}\"` +\n ` (relationColumn \"${relationColumn}\"). Available relations: ${available}`\n )\n }\n\n const nextAlias = `${currentAlias}_${relation.inverseEntityMetadata.tableName}_for_${columnName}`\n\n if (!selectQueryBuilder.expressionMap.aliases.some(alias => alias.name === nextAlias)) {\n selectQueryBuilder[joinType](`${currentAlias}.${column}`, nextAlias)\n }\n if (selectField && columns.at(-1) == column /* 최종 alias만 추가 */) {\n selectQueryBuilder.addSelect(`${nextAlias}.${columnName}`, `${nextAlias}_${columnName}`)\n }\n\n currentAlias = nextAlias\n currentMetadata = relation.inverseEntityMetadata\n }\n\n return currentAlias\n}\n\n/** search 값에 searchMode 에 맞는 와일드카드를 씌운다. */\nfunction wrapSearch(value: string, mode: SearchMode): string {\n switch (mode) {\n case 'startsWith':\n return `${value}%`\n case 'exact':\n return value\n case 'contains':\n default:\n return `%${value}%`\n }\n}\n\n/**\n * Generates the SQL clause and parameters based on the provided filter.\n *\n * @param field - The database field to filter on.\n * @param name - The name of the filter.\n * @param operator - The operator to use in the filter.\n * @param value - The value to filter with.\n * @returns An object containing the SQL clause and the parameters.\n */\nfunction getClauseAndParameters(\n field: string,\n name: string,\n operator: string,\n value: any,\n searchMode: SearchMode = 'contains'\n): { clause: string; parameters: { [key: string]: any } } {\n const values = value instanceof Array ? value : [value]\n let clause = ''\n let parameters: { [key: string]: any } = {}\n\n switch (operator) {\n case 'eq':\n clause = `${field} = :${name}`\n parameters = { [name]: value }\n break\n case 'like':\n clause = `${field} LIKE :${name}`\n parameters = { [name]: `%${value}%` }\n break\n case 'search':\n /* searchMode 로 매칭 방식 선택(기본 contains). startsWith 는 접두 인덱스 활용 가능. */\n clause = `LOWER(${field}) LIKE :${name}`\n parameters = { [name]: wrapSearch(String(value).toLowerCase(), searchMode) }\n break\n case 'i_like':\n clause = `LOWER(${field}) LIKE :${name}`\n parameters = { [name]: `%${String(value).toLowerCase()}%` }\n break\n case 'nlike':\n clause = `${field} NOT LIKE :${name}`\n parameters = { [name]: `%${value}%` }\n break\n case 'i_nlike':\n clause = `LOWER(${field}) NOT LIKE :${name}`\n parameters = { [name]: `%${String(value).toLowerCase()}%` }\n break\n case 'lt':\n clause = `${field} < :${name}`\n parameters = { [name]: value }\n break\n case 'gt':\n clause = `${field} > :${name}`\n parameters = { [name]: value }\n break\n case 'lte':\n clause = `${field} <= :${name}`\n parameters = { [name]: value }\n break\n case 'gte':\n clause = `${field} >= :${name}`\n parameters = { [name]: value }\n break\n case 'noteq':\n clause = `${field} != :${name}`\n parameters = { [name]: value }\n break\n case 'in':\n clause = `${field} IN (:...${name})`\n parameters = { [name]: values }\n break\n case 'notin':\n clause = `${field} NOT IN (:...${name})`\n parameters = { [name]: values }\n break\n case 'notin_with_null':\n clause = `${field} IS NULL OR ${field} NOT IN (:...${name})`\n parameters = { [name]: values }\n break\n case 'is_null':\n clause = `${field} IS NULL`\n break\n case 'is_not_null':\n clause = `${field} IS NOT NULL`\n break\n /* boolean 비교는 파라미터 바인딩으로 (IS TRUE/FALSE 는 MSSQL/Oracle 미지원 → 이식성 확보) */\n case 'is_false':\n clause = `${field} = :${name}`\n parameters = { [name]: false }\n break\n case 'is_true':\n clause = `${field} = :${name}`\n parameters = { [name]: true }\n break\n case 'is_not_false':\n /* NOT FALSE = true 또는 NULL */\n clause = `(${field} IS NULL OR ${field} = :${name})`\n parameters = { [name]: true }\n break\n case 'is_not_true':\n /* NOT TRUE = false 또는 NULL */\n clause = `(${field} IS NULL OR ${field} = :${name})`\n parameters = { [name]: false }\n break\n case 'is_present':\n clause = `${field} IS NOT NULL`\n break\n case 'is_blank':\n clause = `${field} IS NULL`\n break\n case 'is_empty_num_id':\n clause = `(${field} IS NULL OR ${field} = :${name})`\n parameters = { [name]: 0 }\n break\n case 'between':\n clause = `${field} BETWEEN :${name}_1 AND :${name}_2`\n parameters = { [`${name}_1`]: values[0], [`${name}_2`]: values[1] }\n break\n default:\n /* 지원하지 않는 연산자: 이전엔 clause='' 로 andWhere('') 가 되어 malformed/무음이었다.\n 명확한 오류로 원인을 알린다(fail-fast). */\n throw new Error(\n `[getQueryBuilderFromListParams] unsupported filter operator \"${operator}\" for field \"${field}\".`\n )\n }\n\n return { clause, parameters }\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  export * from './get-domain.js';
2
+ export * from './apply-domain-filter.js';
2
3
  export * from './condition-builder.js';
3
4
  export * from './list-query-builder.js';
4
5
  export * from './list-params-converter.js';
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./get-domain.js"), exports);
5
+ tslib_1.__exportStar(require("./apply-domain-filter.js"), exports);
5
6
  tslib_1.__exportStar(require("./condition-builder.js"), exports);
6
7
  tslib_1.__exportStar(require("./list-query-builder.js"), exports);
7
8
  tslib_1.__exportStar(require("./list-params-converter.js"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/utils/index.ts"],"names":[],"mappings":";;;AAAA,0DAA+B;AAC/B,iEAAsC;AACtC,kEAAuC;AACvC,qEAA0C;AAC1C,gEAAqC;AACrC,kFAAuD;AACvD,mEAAwC;AACxC,oEAAyC;AACzC,mEAAwC","sourcesContent":["export * from './get-domain.js'\nexport * from './condition-builder.js'\nexport * from './list-query-builder.js'\nexport * from './list-params-converter.js'\nexport * from './publish-progress.js'\nexport * from './get-query-builder-from-list-params.js'\nexport * from './list-param-adjuster.js'\nexport * from './get-times-for-period.js'\nexport * from './headless-pool/index.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/utils/index.ts"],"names":[],"mappings":";;;AAAA,0DAA+B;AAC/B,mEAAwC;AACxC,iEAAsC;AACtC,kEAAuC;AACvC,qEAA0C;AAC1C,gEAAqC;AACrC,kFAAuD;AACvD,mEAAwC;AACxC,oEAAyC;AACzC,mEAAwC","sourcesContent":["export * from './get-domain.js'\nexport * from './apply-domain-filter.js'\nexport * from './condition-builder.js'\nexport * from './list-query-builder.js'\nexport * from './list-params-converter.js'\nexport * from './publish-progress.js'\nexport * from './get-query-builder-from-list-params.js'\nexport * from './list-param-adjuster.js'\nexport * from './get-times-for-period.js'\nexport * from './headless-pool/index.js'\n"]}
@@ -19,12 +19,14 @@ const OPERATION_FUNCTION_MAP = {
19
19
  notin: value => (0, typeorm_1.Not)((0, typeorm_1.In)(value)),
20
20
  is_null: () => (0, typeorm_1.IsNull)(),
21
21
  is_not_null: () => (0, typeorm_1.Not)((0, typeorm_1.IsNull)()),
22
- is_false: () => (0, typeorm_1.Raw)(alias => `${alias} IS FALSE`),
23
- in_true: () => (0, typeorm_1.Raw)(alias => `${alias} IS TRUE`),
24
- is_not_true: () => (0, typeorm_1.Raw)(alias => `${alias} IS NOT TRUE`),
25
- is_present: () => (0, typeorm_1.Raw)(alias => `${alias} IS PRESENT`),
26
- is_blank: () => (0, typeorm_1.Raw)(alias => `${alias} IS BLANK`),
27
- is_empty_num_id: () => (0, typeorm_1.Raw)(alias => `${alias} IS EMPTY NUMERIC ID`),
22
+ /* boolean 비교는 파라미터 바인딩으로 (IS TRUE/FALSE MSSQL/Oracle 미지원 → 이식성 확보) */
23
+ is_false: () => (0, typeorm_1.Raw)(alias => `${alias} = :val`, { val: false }),
24
+ is_true: () => (0, typeorm_1.Raw)(alias => `${alias} = :val`, { val: true }),
25
+ is_not_false: () => (0, typeorm_1.Raw)(alias => `(${alias} IS NULL OR ${alias} = :val)`, { val: true }),
26
+ is_not_true: () => (0, typeorm_1.Raw)(alias => `(${alias} IS NULL OR ${alias} = :val)`, { val: false }),
27
+ is_present: () => (0, typeorm_1.Raw)(alias => `${alias} IS NOT NULL`),
28
+ is_blank: () => (0, typeorm_1.Raw)(alias => `${alias} IS NULL`),
29
+ is_empty_num_id: () => (0, typeorm_1.Raw)(alias => `(${alias} IS NULL OR ${alias} = :val)`, { val: 0 }),
28
30
  between: value => (0, typeorm_1.Between)(value[0], value[1])
29
31
  };
30
32
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"list-params-converter.js","sourceRoot":"","sources":["../../server/utils/list-params-converter.ts"],"names":[],"mappings":";;AAgKA,8CA6CC;AA7MD,qCAAyF;AAIzF,qEAAwD;AAExD,MAAM,sBAAsB,GAA8D;IACxF,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,eAAK,EAAC,KAAK,CAAC;IAC7B,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,eAAK,EAAC,KAAK,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,aAAG,EAAC,IAAA,eAAK,EAAC,KAAK,CAAC,CAAC;IACjC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,cAAI,EAAC,KAAK,CAAC;IAC1B,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,eAAK,EAAC,KAAK,CAAC;IAC7B,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,aAAG,EAAC,IAAA,cAAI,EAAC,KAAK,CAAC,CAAC;IAChC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,aAAG,EAAC,IAAA,eAAK,EAAC,KAAK,CAAC,CAAC;IACnC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,aAAG,EAAC,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IAChG,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,aAAG,EAAC,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IAChG,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,aAAG,EAAC,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IAClG,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,aAAG,EAAC,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IAClG,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,YAAE,EAAC,KAAK,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,aAAG,EAAC,IAAA,YAAE,EAAC,KAAK,CAAC,CAAC;IAC9B,OAAO,EAAE,GAAG,EAAE,CAAC,IAAA,gBAAM,GAAE;IACvB,WAAW,EAAE,GAAG,EAAE,CAAC,IAAA,aAAG,EAAC,IAAA,gBAAM,GAAE,CAAC;IAChC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAA,aAAG,EAAC,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,WAAW,CAAC;IACjD,OAAO,EAAE,GAAG,EAAE,CAAC,IAAA,aAAG,EAAC,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,UAAU,CAAC;IAC/C,WAAW,EAAE,GAAG,EAAE,CAAC,IAAA,aAAG,EAAC,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,cAAc,CAAC;IACvD,UAAU,EAAE,GAAG,EAAE,CAAC,IAAA,aAAG,EAAC,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,aAAa,CAAC;IACrD,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAA,aAAG,EAAC,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,WAAW,CAAC;IACjD,eAAe,EAAE,GAAG,EAAE,CAAC,IAAA,aAAG,EAAC,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,sBAAsB,CAAC;IACnE,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,IAAA,iBAAO,EAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;CAC9C,CAAA;AAED;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAU;IACtD,OAAO,sBAAsB,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAA;AAChD,CAAC;AAED;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,UAAsB;IAClD,IAAI,MAAM,GAAG,EAAsC,CAAA;IACnD,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,EAAE,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,UAAU,CAAA;QACxC,IAAI,IAAI,GAAG,CAAC,CAAA;QACZ,IAAI,IAAI,GAAG,CAAC,CAAA;QAEZ,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAA;YACpC,IAAI,GAAG,KAAK,CAAA;YACZ,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE;gBACpB,IAAI;gBACJ,IAAI;aACL,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,QAAmB;IAC5C,IAAI,MAAM,GAAG,EAAoD,CAAA;IACjE,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,KAAK,GAAG,EAAwC,CAAA;QACpD,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YACnB,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAA;QACzC,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE;YACpB,KAAK;SACN,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB,CACvB,OAAiB,EACjB,WAAsB;IAItB,2BAA2B;IAC3B,MAAM,aAAa,GACjB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE;QACvB,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjC,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAC3G,OAAO,KAAK,CAAA;QACd,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC,CAAC,IAAI,EAAE,CAAA;IAEV,MAAM,aAAa,GACjB,WAAW,YAAY,KAAK;QAC1B,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE;YACvB,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBACjC,OAAO,KAAK,CAAA;YACd,CAAC;YACD,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvC,OAAO,CAAC,IAAI,CACV,sFAAsF,EACtF,MAAM,CAAC,IAAI,CACZ,CAAA;gBACD,OAAO,KAAK,CAAA;YACd,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC,CAAC,IAAI,EAAE;QACV,CAAC,CAAC,EAAE,CAAA;IAER,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CACtC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QACX,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAA;QACtC,OAAO,KAAK,CAAA;IACd,CAAC,EACD,EAA2C,CAC5C,CAAA;IAED,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO;YACL,KAAK,EAAE,WAAW;SACnB,CAAA;IACH,CAAC;IAED,mDAAmD;IACnD,MAAM,YAAY,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QACzC,OAAO;YACL,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,mBAAmB,CAAC,CAAC,CAAC;YAChC,GAAG,WAAW;SACf,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,KAAK,EAAE,YAAY;KACpB,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,iBAAiB,CAC/B,MAAiB,EACjB,OAKK;IASL,IAAI,QAA4B,CAAA;IAEhC,IAAI,OAAO,EAAE,CAAC;QACZ,IAAI,OAAO,OAAO,KAAK,QAAQ,CAAC,gBAAgB,EAAE,CAAC;YACjD,IAAI,QAAQ,GAAG,OAAO,CAAA;QACxB,CAAC;aAAM,CAAC;YACN,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAA;YACrC,IAAI,QAAQ,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAA;QACjE,CAAC;IACH,CAAC;IAED,IAAI,EAAE,UAAU,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAA;IACnD,IAAI,MAAM,GAAG,EAAE,CAAA;IAEf,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,GAAG,IAAA,sCAAa,EAAC,OAAO,EAAE;YAC/B;gBACE,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,QAAQ;aAChB;SACF,CAAC,CAAA;IACJ,CAAC;IAED,IAAI,UAAU;QAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,UAAU,CAAC,CAAC,CAAA;IACvE,IAAI,QAAQ;QAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAA;IAChE,IAAI,OAAO;QAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAA;IAE1E,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["import { Between, Equal, FindOperator, ILike, In, IsNull, Like, Not, Raw } from 'typeorm'\n\nimport { Filter, ListParam, Pagination, Sorting } from '../service/common-types/list-param.js'\nimport { Domain } from '../service/domain/domain.js'\nimport { adjustFilters } from './list-param-adjuster.js'\n\nconst OPERATION_FUNCTION_MAP: { [operator: string]: (value: any) => FindOperator<any> } = {\n search: value => ILike(value),\n eq: value => Equal(value),\n noteq: value => Not(Equal(value)),\n like: value => Like(value),\n i_like: value => ILike(value),\n nlike: value => Not(Like(value)),\n i_nlike: value => Not(ILike(value)),\n lt: value => Raw(alias => `${alias} < ${typeof value === 'string' ? \"'\" + value + \"'\" : value}`),\n gt: value => Raw(alias => `${alias} > ${typeof value === 'string' ? \"'\" + value + \"'\" : value}`),\n lte: value => Raw(alias => `${alias} <= ${typeof value === 'string' ? \"'\" + value + \"'\" : value}`),\n gte: value => Raw(alias => `${alias} >= ${typeof value === 'string' ? \"'\" + value + \"'\" : value}`),\n in: value => In(value),\n notin: value => Not(In(value)),\n is_null: () => IsNull(),\n is_not_null: () => Not(IsNull()),\n is_false: () => Raw(alias => `${alias} IS FALSE`),\n in_true: () => Raw(alias => `${alias} IS TRUE`),\n is_not_true: () => Raw(alias => `${alias} IS NOT TRUE`),\n is_present: () => Raw(alias => `${alias} IS PRESENT`),\n is_blank: () => Raw(alias => `${alias} IS BLANK`),\n is_empty_num_id: () => Raw(alias => `${alias} IS EMPTY NUMERIC ID`),\n between: value => Between(value[0], value[1])\n}\n\n/**\n * Get the TypeORM FindOperator function for a given filter.\n * @param {Filter} filter - The filter object containing operator and value.\n * @returns {FindOperator<any>} - The corresponding FindOperator function.\n */\nfunction getOperatorFunction({ operator, value }: Filter): FindOperator<any> {\n return OPERATION_FUNCTION_MAP[operator](value)\n}\n\n/**\n * Create pagination parameters for a TypeORM query.\n * @param {Pagination} pagination - The pagination object.\n * @returns {{ skip?: number; take?: number }} - The pagination parameters.\n */\nfunction makePaginationParams(pagination: Pagination): { skip?: number; take?: number } {\n var result = {} as { skip?: number; take?: number }\n if (pagination) {\n var { page = 0, limit = 0 } = pagination\n var skip = 0\n var take = 0\n\n if (limit > 0) {\n skip = Math.max(page - 1, 0) * limit\n take = limit\n Object.assign(result, {\n skip,\n take\n })\n }\n }\n\n return result\n}\n\n/**\n * Create sorting parameters for a TypeORM query.\n * @param {Sorting[]} sortings - The array of sorting objects.\n * @returns {{ order?: { [name: string]: 'DESC' | 'ASC' } }} - The sorting parameters.\n */\nfunction makeSortingParams(sortings: Sorting[]): { order?: { [name: string]: 'DESC' | 'ASC' } } {\n var result = {} as { order?: { [name: string]: 'DESC' | 'ASC' } }\n if (sortings) {\n var order = {} as { [name: string]: 'DESC' | 'ASC' }\n sortings.forEach(s => {\n order[s.name] = s.desc ? 'DESC' : 'ASC'\n })\n\n Object.assign(result, {\n order\n })\n }\n\n return result\n}\n\n/**\n * Create filter parameters for a TypeORM query.\n * @param {Filter[]} filters - The array of filter objects.\n * @param {string[]} searchables - The array of searchable field names.\n * @returns {{ where: { [name: string]: FindOperator<any> } | { [name: string]: FindOperator<any> }[] }} - The filter parameters.\n */\nfunction makeFilterParams(\n filters: Filter[],\n searchables?: string[]\n): {\n where: { [name: string]: FindOperator<any> } | { [name: string]: FindOperator<any> }[]\n} {\n /* for where AND clauses */\n const columnFilters =\n filters?.filter(filter => {\n if (filter.operator === 'search') {\n return false\n }\n if (filter.operator.toLowerCase().includes('like') && (!searchables || !searchables.includes(filter.name))) {\n return false\n }\n return true\n }) || []\n\n const searchFilters =\n searchables instanceof Array\n ? filters?.filter(filter => {\n if (filter.operator !== 'search') {\n return false\n }\n if (!searchables.includes(filter.name)) {\n console.warn(\n '\"searchables\" setting is required for like searches with a heavy database query load',\n filter.name\n )\n return false\n }\n return true\n }) || []\n : []\n\n const columnWhere = columnFilters.reduce(\n (where, f) => {\n where[f.name] = getOperatorFunction(f)\n return where\n },\n {} as { [name: string]: FindOperator<any> }\n )\n\n if (searchFilters.length === 0) {\n return {\n where: columnWhere\n }\n }\n\n /* for fulltext searching ... OR-AND composition */\n const searchWheres = searchFilters.map(f => {\n return {\n [f.name]: getOperatorFunction(f),\n ...columnWhere\n }\n })\n\n return {\n where: searchWheres\n }\n}\n\n/**\n * Convert ListParam object to TypeORM query parameters.\n * @param {ListParam} params - The ListParam object containing pagination, sorting, and filtering options.\n * @param {string | { domain?: string | Domain; searchables?: string[] }} options - Optional domain and searchables parameters.\n * @returns {{ where?: { [name: string]: FindOperator<any> }; order?: { [name: string]: 'DESC' | 'ASC' }; skip?: number; take?: number }} - The TypeORM query parameters.\n */\nexport function convertListParams(\n params: ListParam,\n options?:\n | string\n | {\n domain?: string | Domain\n searchables?: string[]\n }\n): {\n where?: { [name: string]: FindOperator<any> }\n order?: {\n [name: string]: 'DESC' | 'ASC'\n }\n skip?: number\n take?: number\n} {\n var domainId: string | undefined\n\n if (options) {\n if (typeof options === 'string' /* for 하위 호환성 */) {\n var domainId = options\n } else {\n var { domain, searchables } = options\n var domainId = typeof domain === 'string' ? domain : domain?.id\n }\n }\n\n var { pagination, filters = [], sortings } = params\n var result = {}\n\n if (domainId) {\n filters = adjustFilters(filters, [\n {\n name: 'domain',\n operator: 'eq',\n value: domainId\n }\n ])\n }\n\n if (pagination) Object.assign(result, makePaginationParams(pagination))\n if (sortings) Object.assign(result, makeSortingParams(sortings))\n if (filters) Object.assign(result, makeFilterParams(filters, searchables))\n\n return result\n}\n"]}
1
+ {"version":3,"file":"list-params-converter.js","sourceRoot":"","sources":["../../server/utils/list-params-converter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Between, Equal, FindOperator, ILike, In, IsNull, Like, Not, Raw } from 'typeorm'\n\nimport { Filter, ListParam, Pagination, Sorting } from '../service/common-types/list-param.js'\nimport { Domain } from '../service/domain/domain.js'\nimport { adjustFilters } from './list-param-adjuster.js'\n\nconst OPERATION_FUNCTION_MAP: { [operator: string]: (value: any) => FindOperator<any> } = {\n search: value => ILike(value),\n eq: value => Equal(value),\n noteq: value => Not(Equal(value)),\n like: value => Like(value),\n i_like: value => ILike(value),\n nlike: value => Not(Like(value)),\n i_nlike: value => Not(ILike(value)),\n lt: value => Raw(alias => `${alias} < ${typeof value === 'string' ? \"'\" + value + \"'\" : value}`),\n gt: value => Raw(alias => `${alias} > ${typeof value === 'string' ? \"'\" + value + \"'\" : value}`),\n lte: value => Raw(alias => `${alias} <= ${typeof value === 'string' ? \"'\" + value + \"'\" : value}`),\n gte: value => Raw(alias => `${alias} >= ${typeof value === 'string' ? \"'\" + value + \"'\" : value}`),\n in: value => In(value),\n notin: value => Not(In(value)),\n is_null: () => IsNull(),\n is_not_null: () => Not(IsNull()),\n /* boolean 비교는 파라미터 바인딩으로 (IS TRUE/FALSE 는 MSSQL/Oracle 미지원 → 이식성 확보) */\n is_false: () => Raw(alias => `${alias} = :val`, { val: false }),\n is_true: () => Raw(alias => `${alias} = :val`, { val: true }),\n is_not_false: () => Raw(alias => `(${alias} IS NULL OR ${alias} = :val)`, { val: true }),\n is_not_true: () => Raw(alias => `(${alias} IS NULL OR ${alias} = :val)`, { val: false }),\n is_present: () => Raw(alias => `${alias} IS NOT NULL`),\n is_blank: () => Raw(alias => `${alias} IS NULL`),\n is_empty_num_id: () => Raw(alias => `(${alias} IS NULL OR ${alias} = :val)`, { val: 0 }),\n between: value => Between(value[0], value[1])\n}\n\n/**\n * Get the TypeORM FindOperator function for a given filter.\n * @param {Filter} filter - The filter object containing operator and value.\n * @returns {FindOperator<any>} - The corresponding FindOperator function.\n */\nfunction getOperatorFunction({ operator, value }: Filter): FindOperator<any> {\n return OPERATION_FUNCTION_MAP[operator](value)\n}\n\n/**\n * Create pagination parameters for a TypeORM query.\n * @param {Pagination} pagination - The pagination object.\n * @returns {{ skip?: number; take?: number }} - The pagination parameters.\n */\nfunction makePaginationParams(pagination: Pagination): { skip?: number; take?: number } {\n var result = {} as { skip?: number; take?: number }\n if (pagination) {\n var { page = 0, limit = 0 } = pagination\n var skip = 0\n var take = 0\n\n if (limit > 0) {\n skip = Math.max(page - 1, 0) * limit\n take = limit\n Object.assign(result, {\n skip,\n take\n })\n }\n }\n\n return result\n}\n\n/**\n * Create sorting parameters for a TypeORM query.\n * @param {Sorting[]} sortings - The array of sorting objects.\n * @returns {{ order?: { [name: string]: 'DESC' | 'ASC' } }} - The sorting parameters.\n */\nfunction makeSortingParams(sortings: Sorting[]): { order?: { [name: string]: 'DESC' | 'ASC' } } {\n var result = {} as { order?: { [name: string]: 'DESC' | 'ASC' } }\n if (sortings) {\n var order = {} as { [name: string]: 'DESC' | 'ASC' }\n sortings.forEach(s => {\n order[s.name] = s.desc ? 'DESC' : 'ASC'\n })\n\n Object.assign(result, {\n order\n })\n }\n\n return result\n}\n\n/**\n * Create filter parameters for a TypeORM query.\n * @param {Filter[]} filters - The array of filter objects.\n * @param {string[]} searchables - The array of searchable field names.\n * @returns {{ where: { [name: string]: FindOperator<any> } | { [name: string]: FindOperator<any> }[] }} - The filter parameters.\n */\nfunction makeFilterParams(\n filters: Filter[],\n searchables?: string[]\n): {\n where: { [name: string]: FindOperator<any> } | { [name: string]: FindOperator<any> }[]\n} {\n /* for where AND clauses */\n const columnFilters =\n filters?.filter(filter => {\n if (filter.operator === 'search') {\n return false\n }\n if (filter.operator.toLowerCase().includes('like') && (!searchables || !searchables.includes(filter.name))) {\n return false\n }\n return true\n }) || []\n\n const searchFilters =\n searchables instanceof Array\n ? filters?.filter(filter => {\n if (filter.operator !== 'search') {\n return false\n }\n if (!searchables.includes(filter.name)) {\n console.warn(\n '\"searchables\" setting is required for like searches with a heavy database query load',\n filter.name\n )\n return false\n }\n return true\n }) || []\n : []\n\n const columnWhere = columnFilters.reduce(\n (where, f) => {\n where[f.name] = getOperatorFunction(f)\n return where\n },\n {} as { [name: string]: FindOperator<any> }\n )\n\n if (searchFilters.length === 0) {\n return {\n where: columnWhere\n }\n }\n\n /* for fulltext searching ... OR-AND composition */\n const searchWheres = searchFilters.map(f => {\n return {\n [f.name]: getOperatorFunction(f),\n ...columnWhere\n }\n })\n\n return {\n where: searchWheres\n }\n}\n\n/**\n * Convert ListParam object to TypeORM query parameters.\n * @param {ListParam} params - The ListParam object containing pagination, sorting, and filtering options.\n * @param {string | { domain?: string | Domain; searchables?: string[] }} options - Optional domain and searchables parameters.\n * @returns {{ where?: { [name: string]: FindOperator<any> }; order?: { [name: string]: 'DESC' | 'ASC' }; skip?: number; take?: number }} - The TypeORM query parameters.\n */\nexport function convertListParams(\n params: ListParam,\n options?:\n | string\n | {\n domain?: string | Domain\n searchables?: string[]\n }\n): {\n where?: { [name: string]: FindOperator<any> }\n order?: {\n [name: string]: 'DESC' | 'ASC'\n }\n skip?: number\n take?: number\n} {\n var domainId: string | undefined\n\n if (options) {\n if (typeof options === 'string' /* for 하위 호환성 */) {\n var domainId = options\n } else {\n var { domain, searchables } = options\n var domainId = typeof domain === 'string' ? domain : domain?.id\n }\n }\n\n var { pagination, filters = [], sortings } = params\n var result = {}\n\n if (domainId) {\n filters = adjustFilters(filters, [\n {\n name: 'domain',\n operator: 'eq',\n value: domainId\n }\n ])\n }\n\n if (pagination) Object.assign(result, makePaginationParams(pagination))\n if (sortings) Object.assign(result, makeSortingParams(sortings))\n if (filters) Object.assign(result, makeFilterParams(filters, searchables))\n\n return result\n}\n"]}
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildQuery = void 0;
4
4
  const typeorm_1 = require("typeorm");
5
5
  const condition_builder_js_1 = require("./condition-builder.js");
6
+ const apply_domain_filter_js_1 = require("./apply-domain-filter.js");
6
7
  const list_param_js_1 = require("../service/common-types/list-param.js");
7
8
  /**
8
9
  * @deprecated This function is recommended to be replaced with the `getQueryBuilderFromListParams` function.
@@ -68,20 +69,7 @@ const buildQuery = function (queryBuilder, params, context, options) {
68
69
  }
69
70
  if (domainRef) {
70
71
  const inherited = params?.inherited || list_param_js_1.InheritedValueType.None;
71
- if (!inherited || inherited == list_param_js_1.InheritedValueType.None) {
72
- queryBuilder.andWhere(`${queryBuilder.alias}.domain = :domain`, { domain: domain.id });
73
- }
74
- else if (inherited == list_param_js_1.InheritedValueType.Include) {
75
- queryBuilder.andWhere(`${queryBuilder.alias}.domain In(:...domains)`, {
76
- domains: [domain.id, domain.parentId].filter(Boolean)
77
- });
78
- }
79
- else if (inherited == list_param_js_1.InheritedValueType.Only) {
80
- queryBuilder.andWhere(`${queryBuilder.alias}.domain = :domain`, { domain: domain.parentId || 'Impossible' });
81
- }
82
- else {
83
- queryBuilder.andWhere(`${queryBuilder.alias}.domain = :domain`, { domain: 'Impossible' });
84
- }
72
+ (0, apply_domain_filter_js_1.applyDomainInheritanceFilter)(queryBuilder, queryBuilder.alias, domain, inherited);
85
73
  }
86
74
  if (pagination && pagination.page > 0 && pagination.limit > 0) {
87
75
  queryBuilder.skip(pagination.limit * (pagination.page - 1));
@@ -1 +1 @@
1
- {"version":3,"file":"list-query-builder.js","sourceRoot":"","sources":["../../server/utils/list-query-builder.ts"],"names":[],"mappings":"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","sourcesContent":["import { Brackets } from 'typeorm'\n\nimport { buildCondition } from './condition-builder.js'\nimport { Filter, ListParam, InheritedValueType } from '../service/common-types/list-param.js'\n\n/**\n * @deprecated This function is recommended to be replaced with the `getQueryBuilderFromListParams` function.\n *\n * Builds a TypeORM query using the provided parameters to filter, paginate, and sort the data.\n *\n * @param {QueryBuilder} queryBuilder - The TypeORM query builder to build the query on.\n * @param {ListParam} params - The list parameters to apply to the query.\n * @param {Object} context - The context object, typically containing information about the user's domain.\n * @param {boolean|Object} options - Additional options for the query builder.\n * @param {boolean} options.domainRef - Indicates whether to include domain reference in the query.\n * @param {string[]} options.searchables - An array of searchable field names.\n */\nexport const buildQuery = function (\n queryBuilder: any,\n params: ListParam,\n context: any,\n options?:\n | boolean\n | {\n domainRef?: boolean\n searchables?: string[]\n }\n) {\n /* default value of domainRef is 'true' */\n var domainRef = typeof options === 'boolean' ? options : true\n\n /* for backwards compatibility of function spec */\n if (typeof options === 'object') {\n var { domainRef = true, searchables } = options\n }\n\n const columnFilters: Filter[] =\n params.filters?.filter(filter => {\n if (filter.operator === 'search') {\n return false\n }\n if (filter.operator.toLowerCase().includes('like') && (!searchables || !searchables.includes(filter.name))) {\n console.warn(\n '\"searchables\" setting is required for like searches with a heavy database query load',\n filter.name\n )\n return false\n }\n return true\n }) || []\n\n const searchFilters =\n searchables instanceof Array\n ? params.filters?.filter(filter => {\n if (filter.operator !== 'search') {\n return false\n }\n if (!searchables.includes(filter.name)) {\n console.warn(\n '\"searchables\" setting is required for like searches with a heavy database query load',\n filter.name\n )\n return false\n }\n return true\n }) || []\n : []\n\n const pagination = params.pagination\n const sortings = params.sortings\n const domain = context?.state.domain\n\n if (columnFilters && columnFilters.length > 0) {\n columnFilters.forEach(filter => {\n const condition = buildCondition(\n queryBuilder.alias,\n filter.name,\n filter.operator,\n filter.value,\n filter.relation,\n Object.keys(queryBuilder.getParameters()).length\n )\n\n if (condition?.clause) queryBuilder.andWhere(condition.clause)\n if (condition?.parameters) queryBuilder.setParameters(condition.parameters)\n })\n }\n\n if (searchFilters.length > 0) {\n queryBuilder.andWhere(\n new Brackets(qb => {\n searchFilters.forEach((filter, index) => {\n const clause = `${queryBuilder.alias}.${filter.name} LIKE :${filter.name}`\n const parameters = { [filter.name]: filter.value }\n\n index === 0 ? qb.where(clause, parameters) : qb.orWhere(clause, parameters)\n })\n })\n )\n }\n\n if (domainRef) {\n const inherited = params?.inherited || InheritedValueType.None\n\n if (!inherited || inherited == InheritedValueType.None) {\n queryBuilder.andWhere(`${queryBuilder.alias}.domain = :domain`, { domain: domain.id })\n } else if (inherited == InheritedValueType.Include) {\n queryBuilder.andWhere(`${queryBuilder.alias}.domain In(:...domains)`, {\n domains: [domain.id, domain.parentId].filter(Boolean)\n })\n } else if (inherited == InheritedValueType.Only) {\n queryBuilder.andWhere(`${queryBuilder.alias}.domain = :domain`, { domain: domain.parentId || 'Impossible' })\n } else {\n queryBuilder.andWhere(`${queryBuilder.alias}.domain = :domain`, { domain: 'Impossible' })\n }\n }\n\n if (pagination && pagination.page > 0 && pagination.limit > 0) {\n queryBuilder.skip(pagination.limit * (pagination.page - 1))\n queryBuilder.take(pagination.limit)\n }\n\n if (sortings && sortings.length > 0) {\n sortings.forEach((sorting, index) => {\n const sortField = sorting.name.split('.').length > 1 ? sorting.name : `${queryBuilder.alias}.${sorting.name}`\n if (index === 0) {\n queryBuilder.orderBy(sortField, sorting.desc ? 'DESC' : 'ASC')\n } else {\n queryBuilder.addOrderBy(sortField, sorting.desc ? 'DESC' : 'ASC')\n }\n })\n }\n}\n"]}
1
+ {"version":3,"file":"list-query-builder.js","sourceRoot":"","sources":["../../server/utils/list-query-builder.ts"],"names":[],"mappings":"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","sourcesContent":["import { Brackets } from 'typeorm'\n\nimport { buildCondition } from './condition-builder.js'\nimport { applyDomainInheritanceFilter } from './apply-domain-filter.js'\nimport { Filter, ListParam, InheritedValueType } from '../service/common-types/list-param.js'\n\n/**\n * @deprecated This function is recommended to be replaced with the `getQueryBuilderFromListParams` function.\n *\n * Builds a TypeORM query using the provided parameters to filter, paginate, and sort the data.\n *\n * @param {QueryBuilder} queryBuilder - The TypeORM query builder to build the query on.\n * @param {ListParam} params - The list parameters to apply to the query.\n * @param {Object} context - The context object, typically containing information about the user's domain.\n * @param {boolean|Object} options - Additional options for the query builder.\n * @param {boolean} options.domainRef - Indicates whether to include domain reference in the query.\n * @param {string[]} options.searchables - An array of searchable field names.\n */\nexport const buildQuery = function (\n queryBuilder: any,\n params: ListParam,\n context: any,\n options?:\n | boolean\n | {\n domainRef?: boolean\n searchables?: string[]\n }\n) {\n /* default value of domainRef is 'true' */\n var domainRef = typeof options === 'boolean' ? options : true\n\n /* for backwards compatibility of function spec */\n if (typeof options === 'object') {\n var { domainRef = true, searchables } = options\n }\n\n const columnFilters: Filter[] =\n params.filters?.filter(filter => {\n if (filter.operator === 'search') {\n return false\n }\n if (filter.operator.toLowerCase().includes('like') && (!searchables || !searchables.includes(filter.name))) {\n console.warn(\n '\"searchables\" setting is required for like searches with a heavy database query load',\n filter.name\n )\n return false\n }\n return true\n }) || []\n\n const searchFilters =\n searchables instanceof Array\n ? params.filters?.filter(filter => {\n if (filter.operator !== 'search') {\n return false\n }\n if (!searchables.includes(filter.name)) {\n console.warn(\n '\"searchables\" setting is required for like searches with a heavy database query load',\n filter.name\n )\n return false\n }\n return true\n }) || []\n : []\n\n const pagination = params.pagination\n const sortings = params.sortings\n const domain = context?.state.domain\n\n if (columnFilters && columnFilters.length > 0) {\n columnFilters.forEach(filter => {\n const condition = buildCondition(\n queryBuilder.alias,\n filter.name,\n filter.operator,\n filter.value,\n filter.relation,\n Object.keys(queryBuilder.getParameters()).length\n )\n\n if (condition?.clause) queryBuilder.andWhere(condition.clause)\n if (condition?.parameters) queryBuilder.setParameters(condition.parameters)\n })\n }\n\n if (searchFilters.length > 0) {\n queryBuilder.andWhere(\n new Brackets(qb => {\n searchFilters.forEach((filter, index) => {\n const clause = `${queryBuilder.alias}.${filter.name} LIKE :${filter.name}`\n const parameters = { [filter.name]: filter.value }\n\n index === 0 ? qb.where(clause, parameters) : qb.orWhere(clause, parameters)\n })\n })\n )\n }\n\n if (domainRef) {\n const inherited = params?.inherited || InheritedValueType.None\n applyDomainInheritanceFilter(queryBuilder, queryBuilder.alias, domain, inherited)\n }\n\n if (pagination && pagination.page > 0 && pagination.limit > 0) {\n queryBuilder.skip(pagination.limit * (pagination.page - 1))\n queryBuilder.take(pagination.limit)\n }\n\n if (sortings && sortings.length > 0) {\n sortings.forEach((sorting, index) => {\n const sortField = sorting.name.split('.').length > 1 ? sorting.name : `${queryBuilder.alias}.${sorting.name}`\n if (index === 0) {\n queryBuilder.orderBy(sortField, sorting.desc ? 'DESC' : 'ASC')\n } else {\n queryBuilder.addOrderBy(sortField, sorting.desc ? 'DESC' : 'ASC')\n }\n })\n }\n}\n"]}
package/jest.config.js CHANGED
@@ -3,5 +3,10 @@ module.exports = {
3
3
  maxWorkers: 1,
4
4
  preset: 'ts-jest',
5
5
  testEnvironment: 'node',
6
+ // NodeNext 소스는 상대 import 에 .js 확장자를 쓰지만 디스크의 파일은 .ts 이므로
7
+ // ts-jest 가 해석할 수 있도록 상대 import 의 .js 확장자를 제거한다. (bare specifier 는 유지)
8
+ moduleNameMapper: {
9
+ '^(\\.{1,2}/.*)\\.js$': '$1'
10
+ },
6
11
  testMatch: ['**/tests/**/*.[jt]s?(x)', '!**/tests/coverage/**', '!**/tests/utils/**', '!**/tests/images/**']
7
12
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/shell",
3
- "version": "10.0.0-zeta.8",
3
+ "version": "10.0.3",
4
4
  "description": "Core module for framework",
5
5
  "bin": {
6
6
  "things-factory": "bin/things-factory",
@@ -46,18 +46,18 @@
46
46
  "@koa/cors": "^5.0.0",
47
47
  "@material/web": "^2.0.0",
48
48
  "@open-wc/scoped-elements": "^2.1.3",
49
- "@operato/graphql": "^10.0.0-beta.1",
50
- "@operato/help": "^10.0.0-beta.1",
51
- "@operato/layout": "^10.0.0-beta.1",
52
- "@operato/shell": "^10.0.0-beta.1",
53
- "@operato/typeorm-history": "^10.0.0-beta.1",
54
- "@operato/utils": "^10.0.0-beta.1",
49
+ "@operato/graphql": "^10.0.0",
50
+ "@operato/help": "^10.0.0",
51
+ "@operato/layout": "^10.0.0",
52
+ "@operato/shell": "^10.0.0",
53
+ "@operato/typeorm-history": "^10.0.0",
54
+ "@operato/utils": "^10.0.0",
55
55
  "@reduxjs/toolkit": "^2.2.5",
56
- "@things-factory/ejs-remote": "^10.0.0-zeta.8",
57
- "@things-factory/env": "^10.0.0-zeta.8",
56
+ "@things-factory/ejs-remote": "^10.0.0",
57
+ "@things-factory/env": "^10.0.0",
58
58
  "@things-factory/operato-license-checker": "^4.0.4",
59
- "@things-factory/styles": "^10.0.0-zeta.8",
60
- "@things-factory/utils": "^10.0.0-zeta.8",
59
+ "@things-factory/styles": "^10.0.0",
60
+ "@things-factory/utils": "^10.0.0",
61
61
  "@types/koa": "^3.0.1",
62
62
  "@types/koa-bodyparser": "^4.3.13",
63
63
  "@webcomponents/scoped-custom-element-registry": "^0.0.9",
@@ -126,5 +126,5 @@
126
126
  "pg": "^8.7.3",
127
127
  "sqlite3": "^5.0.8"
128
128
  },
129
- "gitHead": "75dddca7d209c85b5380637490fbe95d3df67d4e"
129
+ "gitHead": "c7d253b722b6917e8911f6ef6e78e5fc2b295e82"
130
130
  }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * `domains.owner` 인덱스 — 실제 엔티티 메타데이터와 실제 마이그레이션으로 검증.
3
+ *
4
+ * 운영 설정은 `synchronize: false` 이므로 두 경로를 따로 확인한다.
5
+ * - 엔티티 `@Index` 선언 → 신규 설치 경로
6
+ * - `IndexDomainOwner` 마이그레이션 → 기존 설치 경로
7
+ */
8
+
9
+ import { DataSource, IsNull, QueryRunner, TableIndex } from 'typeorm'
10
+
11
+ import { Domain, NamingStrategy, entities as shellEntities } from '@things-factory/shell'
12
+
13
+ import { IndexDomainOwner1785369600000 } from '../server/migrations/1785369600000-IndexDomainOwner.js'
14
+
15
+ const INDEX_NAME = 'ix_domain_1'
16
+
17
+ let dataSource: DataSource
18
+ let queryRunner: QueryRunner
19
+
20
+ async function findIndex(): Promise<TableIndex | undefined> {
21
+ const table = await queryRunner.getTable('domains')
22
+ return table?.indices.find(index => index.name === INDEX_NAME)
23
+ }
24
+
25
+ async function saveDomain(name: string, owner?: string): Promise<Domain> {
26
+ return await dataSource.getRepository(Domain).save({ name, subdomain: name, owner } as any)
27
+ }
28
+
29
+ beforeAll(async () => {
30
+ dataSource = new DataSource({
31
+ type: 'sqlite',
32
+ database: ':memory:',
33
+ synchronize: true,
34
+ dropSchema: true,
35
+ namingStrategy: new NamingStrategy(),
36
+ entities: [...shellEntities],
37
+ logging: false
38
+ })
39
+
40
+ await dataSource.initialize()
41
+ queryRunner = dataSource.createQueryRunner()
42
+ })
43
+
44
+ afterAll(async () => {
45
+ await queryRunner?.release()
46
+ await dataSource?.destroy()
47
+ })
48
+
49
+ describe('엔티티 선언 (신규 설치)', () => {
50
+ it('owner 컬럼에 인덱스가 생성된다', async () => {
51
+ const index = await findIndex()
52
+
53
+ expect(index).toBeDefined()
54
+ expect(index.columnNames).toEqual(['owner'])
55
+ })
56
+
57
+ it('non-unique 라서 한 사용자가 여러 도메인을 소유할 수 있다', async () => {
58
+ expect((await findIndex()).isUnique).toBe(false)
59
+
60
+ const owner = 'same-owner-id'
61
+ await saveDomain('multi-a', owner)
62
+ await saveDomain('multi-b', owner)
63
+
64
+ expect(await dataSource.getRepository(Domain).count({ where: { owner } })).toBe(2)
65
+ })
66
+
67
+ it('owner 가 비어 있는 도메인도 여러 개 존재할 수 있다', async () => {
68
+ await saveDomain('orphan-a')
69
+ await saveDomain('orphan-b')
70
+
71
+ const orphans = await dataSource.getRepository(Domain).find({ where: { owner: IsNull() } })
72
+
73
+ expect(orphans.map(domain => domain.subdomain).sort()).toEqual(['orphan-a', 'orphan-b'])
74
+ })
75
+ })
76
+
77
+ describe('마이그레이션 (기존 설치)', () => {
78
+ const migration = new IndexDomainOwner1785369600000()
79
+
80
+ afterEach(async () => {
81
+ /* 다음 검사를 위해 인덱스를 되돌려 둔다. */
82
+ if (!(await findIndex())) {
83
+ await migration.up(queryRunner)
84
+ }
85
+ })
86
+
87
+ it('인덱스가 없는 DB 에 인덱스를 만든다', async () => {
88
+ await queryRunner.dropIndex('domains', INDEX_NAME)
89
+ expect(await findIndex()).toBeUndefined()
90
+
91
+ await migration.up(queryRunner)
92
+
93
+ const index = await findIndex()
94
+ expect(index.columnNames).toEqual(['owner'])
95
+ expect(index.isUnique).toBe(false)
96
+ })
97
+
98
+ it('이미 있으면 아무것도 하지 않는다 (idempotent)', async () => {
99
+ expect(await findIndex()).toBeDefined()
100
+
101
+ await expect(migration.up(queryRunner)).resolves.not.toThrow()
102
+
103
+ expect(await findIndex()).toBeDefined()
104
+ })
105
+
106
+ it('되돌리면 인덱스만 사라지고 데이터는 남는다', async () => {
107
+ const saved = await saveDomain('rollback-target', 'owner-id')
108
+
109
+ await migration.down(queryRunner)
110
+
111
+ expect(await findIndex()).toBeUndefined()
112
+ expect((await dataSource.getRepository(Domain).findOneBy({ id: saved.id })).owner).toBe('owner-id')
113
+ })
114
+
115
+ it('인덱스가 없는 상태에서 되돌려도 실패하지 않는다', async () => {
116
+ await migration.down(queryRunner)
117
+ expect(await findIndex()).toBeUndefined()
118
+
119
+ await expect(migration.down(queryRunner)).resolves.not.toThrow()
120
+ })
121
+ })