@pcg/core 1.0.0-alpha.1 → 1.0.0-alpha.2

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 (98) hide show
  1. package/dist/index.d.ts +21 -1179
  2. package/dist/index.js +76 -1856
  3. package/dist/index.js.map +1 -1
  4. package/package.json +16 -4
  5. package/.turbo/turbo-build.log +0 -16
  6. package/CHANGELOG.md +0 -14
  7. package/src/abstracts/index.ts +0 -3
  8. package/src/abstracts/nestjs-resource-service.ts +0 -154
  9. package/src/abstracts/nestjs-service.ts +0 -25
  10. package/src/configs/app.config.ts +0 -185
  11. package/src/configs/db.config.ts +0 -122
  12. package/src/configs/index.ts +0 -4
  13. package/src/configs/logger.config.ts +0 -62
  14. package/src/context/action-context.ts +0 -34
  15. package/src/context/current-user.ts +0 -49
  16. package/src/context/index.ts +0 -5
  17. package/src/context/platform-method-context.ts +0 -5
  18. package/src/context/service-method-context.ts +0 -47
  19. package/src/db/snake-naming.strategy.ts +0 -277
  20. package/src/enums/app-env.enum.ts +0 -36
  21. package/src/enums/app-mode.enum.ts +0 -5
  22. package/src/enums/app-server.enum.ts +0 -39
  23. package/src/enums/index.ts +0 -4
  24. package/src/enums/worker-mode.enum.ts +0 -11
  25. package/src/errors/access-denied.error.ts +0 -18
  26. package/src/errors/bad-request.error.ts +0 -9
  27. package/src/errors/forbidden.error.ts +0 -9
  28. package/src/errors/index.ts +0 -8
  29. package/src/errors/input-validation.error.ts +0 -16
  30. package/src/errors/nest-error.filter.ts +0 -70
  31. package/src/errors/nest-error.ts +0 -63
  32. package/src/errors/not-found.error.ts +0 -9
  33. package/src/errors/unauthorized.error.ts +0 -9
  34. package/src/exceptions/http-exception-response.ts +0 -34
  35. package/src/exceptions/http-exceptions.filter.ts +0 -95
  36. package/src/index.ts +0 -32
  37. package/src/jwt/extractors.ts +0 -80
  38. package/src/jwt/types.ts +0 -209
  39. package/src/logger/classes/logger-factory.ts +0 -54
  40. package/src/logger/classes/logger.ts +0 -340
  41. package/src/logger/classes/nest-system-logger.ts +0 -63
  42. package/src/logger/classes/typeorm-logger.ts +0 -83
  43. package/src/logger/index.ts +0 -20
  44. package/src/logger/logger.constants.ts +0 -24
  45. package/src/logger/logger.interfaces.ts +0 -98
  46. package/src/logger/logger.module.ts +0 -45
  47. package/src/logger/logger.providers.ts +0 -140
  48. package/src/logger/winston.tools.ts +0 -241
  49. package/src/middlewares/app.middleware.ts +0 -26
  50. package/src/middlewares/index.ts +0 -1
  51. package/src/modules/hooks/base-hook.ts +0 -64
  52. package/src/modules/hooks/decorators/on-hook.decorator.ts +0 -19
  53. package/src/modules/hooks/hooks.module.ts +0 -10
  54. package/src/modules/hooks/hooks.service.ts +0 -28
  55. package/src/modules/hooks/index.ts +0 -11
  56. package/src/modules/id/id.module.ts +0 -26
  57. package/src/modules/id/id.service.ts +0 -57
  58. package/src/modules/id/index.ts +0 -2
  59. package/src/modules/postgres-pubsub/index.ts +0 -3
  60. package/src/modules/postgres-pubsub/postgres-pubsub.module.ts +0 -14
  61. package/src/modules/postgres-pubsub/postgres-pubsub.ts +0 -461
  62. package/src/pagination/constants.ts +0 -9
  63. package/src/pagination/cursor/cursor-pagination.exception.ts +0 -16
  64. package/src/pagination/cursor/cursor-pagination.helpers.ts +0 -145
  65. package/src/pagination/cursor/cursor-pagination.input.ts +0 -96
  66. package/src/pagination/cursor/cursor-pagination.types.ts +0 -127
  67. package/src/pagination/index.ts +0 -9
  68. package/src/pagination/offset/offset-pagination.exception.ts +0 -15
  69. package/src/pagination/offset/offset-pagination.helpers.ts +0 -122
  70. package/src/pagination/offset/offset-pagination.input.ts +0 -30
  71. package/src/pagination/offset/offset-pagination.types.ts +0 -82
  72. package/src/pagination/tools.ts +0 -53
  73. package/src/tools/compose.ts +0 -92
  74. package/src/tools/convert-to-bigint.ts +0 -27
  75. package/src/tools/create-list-meta.ts +0 -64
  76. package/src/tools/define-statuses.ts +0 -15
  77. package/src/tools/env.ts +0 -139
  78. package/src/tools/fetch-total-with-query.ts +0 -48
  79. package/src/tools/generate-entity-id.ts +0 -23
  80. package/src/tools/get-request-language.ts +0 -13
  81. package/src/tools/is-object.ts +0 -1
  82. package/src/tools/postgres/locale-to-pg-collate.ts +0 -21
  83. package/src/tools/remove-undefined-properties.ts +0 -20
  84. package/src/tools/request-id.ts +0 -25
  85. package/src/tools/stringify-opts.ts +0 -20
  86. package/src/tools/typeorm/add-filter.ts +0 -164
  87. package/src/tools/typeorm/ensure-inner-join.ts +0 -36
  88. package/src/tools/typeorm/ensure-left-join.ts +0 -36
  89. package/src/tools/typeorm/is-alias-already-busy.ts +0 -25
  90. package/src/tools/wait.ts +0 -26
  91. package/src/types/express-request.ts +0 -8
  92. package/src/types/list-mehod-options.ts +0 -32
  93. package/src/types/list-meta.ts +0 -16
  94. package/src/types/maybe.ts +0 -2
  95. package/src/validation/index.ts +0 -1
  96. package/src/validation/validation-pipe.ts +0 -14
  97. package/tsconfig.lib.json +0 -9
  98. package/tsdown.config.ts +0 -15
@@ -1,64 +0,0 @@
1
- import { ListMeta } from '#/types/list-meta';
2
- import type { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
3
- import { fetchTotalWithQuery } from './fetch-total-with-query.js';
4
-
5
- export interface CreateListMetaOptions<T extends ObjectLiteral> {
6
- /**
7
- * Typeorm query builder
8
- */
9
- query: SelectQueryBuilder<T>;
10
-
11
- /**
12
- * If true, total count will be calculated by additional SELECT COUNT.
13
- */
14
- needCountTotal?: boolean;
15
-
16
- /**
17
- * Limit of items
18
- */
19
- limit?: number;
20
-
21
- /**
22
- * Offset of items
23
- */
24
- offset?: number;
25
- }
26
-
27
- /**
28
- * Create list meta object
29
- * @returns list meta object
30
- * @example
31
- * class UsersService {
32
- * async getMany(opts: GetManyUsersOptions): Promise<[User[], ListMeta]> {
33
- * ...
34
- * return Promise.all([
35
- * query.getMany(),
36
- * createListMeta<User>({
37
- * query,
38
- * needCountTotal,
39
- * limit,
40
- * offset,
41
- * }),
42
- * ]);
43
- * }
44
- */
45
- export const createListMeta = async <T extends ObjectLiteral>(
46
- {
47
- query,
48
- needCountTotal = false,
49
- limit,
50
- offset,
51
- }: CreateListMetaOptions<T>,
52
- ): Promise<ListMeta> => {
53
- const meta: ListMeta = {
54
- limit,
55
- offset,
56
- };
57
-
58
- if (needCountTotal) {
59
- meta.total = await fetchTotalWithQuery(query);
60
- }
61
-
62
- return meta;
63
- };
64
-
@@ -1,15 +0,0 @@
1
- /**
2
- * Define statuses. Returns array of statuses from filter or default statuses
3
- * @param statuses - array of statuses from filter. Can be undefined
4
- * @param defaultStatuses - array of default statuses
5
- * @returns final array of statuses
6
- * @example
7
- * const statuses = defineStatuses(['active', 'pending'], ['active']);
8
- * // statuses = ['active', 'pending']
9
- *
10
- * const statuses = defineStatuses(undefined, ['active']);
11
- * // statuses = ['active']
12
- */
13
- export const defineStatuses = <T>(statuses: T[] | undefined, defaultStatuses: T[]) => {
14
- return Array.isArray(statuses) ? statuses : defaultStatuses;
15
- };
package/src/tools/env.ts DELETED
@@ -1,139 +0,0 @@
1
- import { Type as ClassConstructor } from '@nestjs/common';
2
- import { plainToInstance } from 'class-transformer';
3
- import { validateSync } from 'class-validator';
4
-
5
- import { AppEnv } from '#/enums/app-env.enum';
6
-
7
- /**
8
- * Validate environment variables using class-validator
9
- *
10
- * @param cls - class with environment variables
11
- * @throws Error if validation fails
12
- * @returns validated config as typed object
13
- * @example
14
- * ```ts
15
- * export class AppConfigEnvironmentVariables {
16
- * @Type(() => Number)
17
- * @IsNumber()
18
- * PORT = 3000;
19
- * }
20
- *
21
- * const env = validateEnv(AppConfigEnvironmentVariables); // typed object
22
- * // env.PORT is now a number
23
- * ```
24
- */
25
- export const validateEnv = <T>(cls: ClassConstructor<T>): T => {
26
- const validatedConfig = plainToInstance(
27
- cls,
28
- process.env,
29
- {
30
- enableImplicitConversion: true,
31
- },
32
- );
33
-
34
- const errors = validateSync(validatedConfig as unknown as object, {
35
- skipMissingProperties: false,
36
- });
37
-
38
- if (errors.length > 0) {
39
- throw new Error(errors.toString());
40
- }
41
-
42
- return validatedConfig;
43
- };
44
-
45
- /**
46
- * Returns a string with a dash prefix based on the current environment.
47
- * If the environment is development or local, returns '-dev'.
48
- * If the environment is stage, returns '-stage'.
49
- * Otherwise, returns an empty string.
50
- *
51
- * @returns a string with a dash prefix based on the current environment
52
- * @example
53
- * ```typescript
54
- * const name = `my-app${withDashEnv()}`;
55
- * ```
56
- */
57
- export const withDashEnv = () => {
58
- if (process.env.APP_ENV === AppEnv.DEVELOPMENT || process.env.APP_ENV === AppEnv.LOCAL || process.env.APP_ENV === AppEnv.TEST) {
59
- return '-dev';
60
- }
61
-
62
- if (process.env.APP_ENV === AppEnv.STAGE) {
63
- return '-stage';
64
- }
65
-
66
- return '';
67
- };
68
-
69
- /**
70
- * Returns a string with a dash prefix based on the current environment.
71
- * If the environment is development or local, returns '.dev'.
72
- * If the environment is stage, returns '.stage'.
73
- * Otherwise, returns an empty string.
74
- *
75
- * @returns a string with a dot prefix based on the current environment
76
- * @example
77
- * ```typescript
78
- * const name = `config${withDotEnv()}`;
79
- * ```
80
- */
81
- export const withDotEnv = () => {
82
- if (process.env.APP_ENV === AppEnv.DEVELOPMENT || process.env.APP_ENV === AppEnv.LOCAL || process.env.APP_ENV === AppEnv.TEST) {
83
- return '.dev';
84
- }
85
-
86
- if (process.env.APP_ENV === AppEnv.STAGE) {
87
- return '.stage';
88
- }
89
-
90
- return '';
91
- };
92
-
93
- /**
94
- * Returns a string with a colon prefix based on the current environment.
95
- * If the environment is development or local, returns ':dev'.
96
- * If the environment is stage, returns ':stage'.
97
- * Otherwise, returns an empty string.
98
- *
99
- * @returns a string with a colon prefix based on the current environment
100
- * @example
101
- * ```typescript
102
- * const name = `my:app${withColonEnv()}`;
103
- * ```
104
- */
105
- export const withColonEnv = () => {
106
- if (process.env.APP_ENV === AppEnv.DEVELOPMENT || process.env.APP_ENV === AppEnv.LOCAL || process.env.APP_ENV === AppEnv.TEST) {
107
- return ':dev';
108
- }
109
-
110
- if (process.env.APP_ENV === AppEnv.STAGE) {
111
- return ':stage';
112
- }
113
-
114
- return '';
115
- };
116
-
117
- /**
118
- * Returns a string with an underscore prefix based on the current environment.
119
- * If the environment is development or local, returns '_dev'.
120
- * If the environment is stage, returns '_stage'.
121
- * Otherwise, returns an empty string.
122
- *
123
- * @returns a string with an underscore prefix based on the current environment
124
- * @example
125
- * ```typescript
126
- * const name = `my_app${withUnderscoreEnv()}`;
127
- * ```
128
- */
129
- export const withUnderscoreEnv = () => {
130
- if (process.env.APP_ENV === AppEnv.DEVELOPMENT || process.env.APP_ENV === AppEnv.LOCAL || process.env.APP_ENV === AppEnv.TEST) {
131
- return '_dev';
132
- }
133
-
134
- if (process.env.APP_ENV === AppEnv.STAGE) {
135
- return '_stage';
136
- }
137
-
138
- return '';
139
- };
@@ -1,48 +0,0 @@
1
- import { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
2
-
3
- /**
4
- * Returns total count of items with typeorm query
5
- * @param query - typeorm query builder
6
- * @returns total count of items
7
- */
8
- /**
9
- * Returns total count of items with typeorm query
10
- * @param query - typeorm query builder
11
- * @returns total count of items
12
- */
13
- export const fetchTotalWithQuery = async <T extends ObjectLiteral>(
14
- query: SelectQueryBuilder<T>,
15
- ): Promise<number> => {
16
- const totalQueryBuilder = query.clone();
17
-
18
- // Clear any pagination settings
19
- totalQueryBuilder
20
- .offset(undefined)
21
- .limit(undefined)
22
- .skip(undefined)
23
- .take(undefined)
24
- .orderBy();
25
-
26
- const hasDistinctOn = totalQueryBuilder.expressionMap.selectDistinctOn && totalQueryBuilder.expressionMap.selectDistinctOn.length > 0;
27
- const isGrouped = totalQueryBuilder.expressionMap.groupBys && totalQueryBuilder.expressionMap.groupBys.length > 0;
28
-
29
- // Check if the original query has DISTINCT ON or GROUP BY
30
- if (hasDistinctOn || isGrouped) {
31
- // Wrap the query (either with DISTINCT ON or GROUP BY) in a subquery and count the results
32
- const subQuery = totalQueryBuilder.getQuery();
33
-
34
- const result = await query.connection
35
- .createQueryBuilder()
36
- .select('COUNT(*)', 'rowsCount')
37
- .from(`(${subQuery})`, 'subQuery')
38
- .setParameters(totalQueryBuilder.getParameters())
39
- .getRawOne<{
40
- rowsCount: number;
41
- }>();
42
-
43
- return result?.rowsCount ?? 0;
44
- }
45
-
46
- // If no DISTINCT ON or GROUP BY, just get the count directly
47
- return await totalQueryBuilder.getCount();
48
- };
@@ -1,23 +0,0 @@
1
- import { createRandomString } from '@pcg/text-kit';
2
-
3
- /**
4
- * Generates a unique entity identifier by combining product name, entity prefix, delimiter, and random string.
5
- *
6
- * @param product - The product short name to include in the entity ID (e.g., 'fwd' for Forward)
7
- * @param prefix - The entity type prefix to include in the entity ID (e.g., 'u' for user, 'org' for organization)
8
- * @param delimiter - The delimiter to separate components (default: ':')
9
- * @param size - The length of the random string component (default: 11)
10
- * @returns A formatted entity ID string in the format: `${product}${prefix}${delimiter}${randomString}`
11
- *
12
- * @example
13
- * ```typescript
14
- * generateEntityId('fwd', 'org')
15
- * // Returns: 'fwdorg:A1b2C3d4E5f'
16
- *
17
- * generateEntityId('myapp', 'u', '_', 8)
18
- * // Returns: 'myappuser_A1b2C3d4'
19
- * ```
20
- */
21
- export const generateEntityId = (product: string, prefix: string, delimiter = ':', size = 11): string => {
22
- return `${product}${prefix}${delimiter}${createRandomString(size)}`;
23
- };
@@ -1,13 +0,0 @@
1
- import { parse } from 'accept-language-parser';
2
-
3
- import { NestExpressRequest } from '#/types/express-request';
4
-
5
- export const getRequestLanguage = (req: NestExpressRequest, fallbackLanguage: string): string => {
6
- const headers = req?.headers as ({
7
- ['accept-language']?: string;
8
- });
9
-
10
- return parse(headers['accept-language'])
11
- ?.[0]
12
- ?.code ?? fallbackLanguage;
13
- };
@@ -1 +0,0 @@
1
- export { isObject } from '@pcg/predicates';
@@ -1,21 +0,0 @@
1
- /**
2
- * Converts a locale string to a PostgreSQL collation identifier.
3
- *
4
- * @param locale - The locale string to convert (e.g., 'uk', 'en')
5
- * @returns The PostgreSQL collation identifier (e.g., 'uk_UA', 'en_US')
6
- *
7
- * @example
8
- * ```typescript
9
- * localeToPgCollate('uk') // returns 'uk_UA'
10
- * localeToPgCollate('en') // returns 'en_US'
11
- * ```
12
- */
13
- export const localeToPgCollate = (locale: string) => {
14
- let collate = 'en_US';
15
-
16
- if (locale === 'uk') {
17
- collate = 'uk_UA';
18
- }
19
-
20
- return collate;
21
- };
@@ -1,20 +0,0 @@
1
- type DefinedValuesOnly<T> = {
2
- [K in keyof T]: T[K] extends undefined ? never : K;
3
- }[keyof T];
4
-
5
- type UndefinedRemoved<T> = {
6
- [K in DefinedValuesOnly<T>]: T[K];
7
- };
8
-
9
- export const removeUndefinedProperties = <T extends object>(obj: T): UndefinedRemoved<T> => {
10
- const result: Partial<UndefinedRemoved<T>> = {
11
- };
12
-
13
- for (const key in obj) {
14
- if (Object.prototype.hasOwnProperty.call(obj, key) && obj[key as keyof T] !== undefined) {
15
- (result as Record<string, unknown>)[key] = obj[key as keyof T];
16
- }
17
- }
18
-
19
- return result as UndefinedRemoved<T>;
20
- };
@@ -1,25 +0,0 @@
1
- import { createRandomString } from '@pcg/text-kit';
2
-
3
- import { NestExpressRequest } from '#/types/express-request';
4
-
5
-
6
- export const generateRequestId = (appShortName: string) => {
7
- return `${appShortName}req:${createRandomString()}`;
8
- };
9
-
10
- export const extractRequestId = (req: NestExpressRequest): string => {
11
- const headers = req?.headers as ({
12
- 'x-request-id'?: string;
13
- 'x-cloud-trace-context'?: string;
14
- });
15
-
16
- if (headers?.['x-request-id']) {
17
- return headers['x-request-id'];
18
- }
19
-
20
- if (headers['x-cloud-trace-context']) {
21
- return req.appShortname + `req:${headers['x-cloud-trace-context']}`;
22
- }
23
-
24
- return generateRequestId(req.appShortname);
25
- };
@@ -1,20 +0,0 @@
1
- /**
2
- * Converts an object into a human-readable string representation.
3
- *
4
- * Takes an object and transforms it into a string where each key-value pair
5
- * is formatted as "key JSON-value" and all pairs are joined with " and ".
6
- *
7
- * @param opts - The object to stringify
8
- * @returns A string representation of the object with entries joined by " and "
9
- *
10
- * @example
11
- * ```ts
12
- * stringifyOpts({ name: 'John', age: 30 })
13
- * // Returns: 'name "John" and age 30'
14
- * ```
15
- */
16
- export const stringifyOpts = (opts: object) => {
17
- return Object.entries(opts)
18
- .map(([key, value]) => `${key} ${JSON.stringify(value)}`)
19
- .join(' and ');
20
- };
@@ -1,164 +0,0 @@
1
- import {
2
- Brackets, In, IsNull, ObjectLiteral, SelectQueryBuilder, WhereExpressionBuilder,
3
- } from 'typeorm';
4
-
5
- import { MaybeNull } from '#/types/maybe';
6
-
7
- /**
8
- * Adds a filter condition to a TypeORM SelectQueryBuilder based on the provided field and value(s).
9
- *
10
- * Handles three types of filtering:
11
- * - Single value filtering: when a single non-null value is provided
12
- * - Multiple value filtering: when an array of values is provided
13
- * - Null value filtering: when null is explicitly provided as the filter value
14
- *
15
- * @template T - The entity type that extends ObjectLiteral
16
- * @template K - The field name key type that must be a string key of T
17
- *
18
- * @param query - The TypeORM SelectQueryBuilder instance to add the filter to
19
- * @param fieldName - The name of the field to filter by, must be a valid key of entity T
20
- * @param valueOrValues - The filter value(s). Can be:
21
- * - A single value of type T[K]
22
- * - An array of values of type T[K]
23
- * - null to filter for null values
24
- * - An array containing null values
25
- * @example
26
- * ```typescript
27
- * // Single value filter
28
- * addFilterByField(queryBuilder, 'status', 'active');
29
- * // Multiple values filter
30
- * addFilterByField(queryBuilder, 'id', [1, 2, 3]);
31
- * // Null value filter
32
- * addFilterByField(queryBuilder, 'deletedAt', null);
33
- * ```
34
- *
35
- * @returns void - Modifies the query builder in place
36
- */
37
- export const addFilterByField = <
38
- T extends ObjectLiteral,
39
- K extends (keyof T & string)
40
- >(query: SelectQueryBuilder<T>, fieldName: K, valueOrValues: MaybeNull<T[K]> | MaybeNull<T[K]>[]): void => {
41
- const isFilterValueMultiple = Array.isArray(valueOrValues);
42
-
43
- if (isFilterValueMultiple) {
44
- addMultipleFilter(query, fieldName, valueOrValues);
45
- } else if (valueOrValues === null) {
46
- addNullableFilter(query, fieldName);
47
- } else {
48
- addSingleFilter(query, fieldName, valueOrValues);
49
- }
50
- };
51
-
52
- /**
53
- * Adds a filter to a TypeORM query that matches multiple values for a given column,
54
- * including support for null values.
55
- *
56
- * @template T - The entity type that extends ObjectLiteral
57
- * @template K - The key type that must be both a key of T and a string
58
- * @param query - The TypeORM SelectQueryBuilder instance to add the filter to
59
- * @param columnName - The name of the column to filter on
60
- * @param values - An array of values to match, which may include null
61
- *
62
- * @remarks
63
- * This function creates an OR condition that matches any of the provided values.
64
- * If the values array includes null, a separate null check is added to the filter.
65
- * Non-null values are handled using TypeORM's `In` operator.
66
- *
67
- * @example
68
- * ```typescript
69
- * const query = repository.createQueryBuilder('user');
70
- * addMultipleFilter(query, 'status', ['active', 'pending', null]);
71
- * // Generates: WHERE (status IS NULL OR status IN ('active', 'pending'))
72
- * ```
73
- */
74
- const addMultipleFilter = <
75
- T extends ObjectLiteral,
76
- K extends (keyof T & string)
77
- >(query: SelectQueryBuilder<T>, columnName: K, values: MaybeNull<T[K]>[]): void => {
78
- query.andWhere(new Brackets((subQuery) => {
79
- if (values.includes(null)) {
80
- addNullValueToMultipleFilter(subQuery, columnName);
81
- }
82
-
83
- const notNullValues = values.filter((v) => v !== null);
84
- subQuery.orWhere({
85
- [columnName]: In(notNullValues),
86
- });
87
- }));
88
- };
89
-
90
- /**
91
- * Adds a single filter condition to a TypeORM SelectQueryBuilder.
92
- *
93
- * @template T - The entity type that extends ObjectLiteral
94
- * @template K - The column name type, constrained to string keys of T
95
- *
96
- * @param query - The SelectQueryBuilder instance to add the filter to
97
- * @param columnName - The name of the column to filter on
98
- * @param value - The value to filter by, must match the type of the column
99
- *
100
- * @returns void
101
- *
102
- * @example
103
- * ```typescript
104
- * const query = repository.createQueryBuilder('user');
105
- * addSingleFilter(query, 'email', 'user@example.com');
106
- * // Results in: WHERE user.email = 'user@example.com'
107
- * ```
108
- */
109
- const addSingleFilter = <
110
- T extends ObjectLiteral,
111
- K extends (keyof T & string)
112
- >(query: SelectQueryBuilder<T>, columnName: K, value: T[K]): void => {
113
- query.andWhere({
114
- [columnName]: value,
115
- });
116
- };
117
-
118
- /**
119
- * Adds a nullable filter to a TypeORM query builder.
120
- *
121
- * This function applies a WHERE clause that filters for NULL values in the specified column.
122
- * The filter is combined with existing conditions using AND logic.
123
- *
124
- * @template T - The entity type that extends ObjectLiteral
125
- * @param query - The TypeORM SelectQueryBuilder instance to add the filter to
126
- * @param columnName - The name of the column to check for NULL values
127
- * @returns void
128
- *
129
- * @example
130
- * ```typescript
131
- * const query = repository.createQueryBuilder('user');
132
- * addNullableFilter(query, 'deletedAt');
133
- * // Results in: WHERE deletedAt IS NULL
134
- * ```
135
- */
136
- const addNullableFilter = <T extends ObjectLiteral>(query: SelectQueryBuilder<T>, columnName: string): void => {
137
- query.andWhere({
138
- [columnName]: IsNull(),
139
- });
140
- };
141
-
142
- /**
143
- * Adds an OR condition to the query to check if the specified column is NULL.
144
- *
145
- * This function is used to extend filtering logic by adding a null value check
146
- * as an alternative condition in a WHERE clause.
147
- *
148
- * @param query - The TypeORM WhereExpressionBuilder instance to which the null condition will be added
149
- * @param columnName - The name of the database column to check for NULL values
150
- *
151
- * @returns void
152
- *
153
- * @example
154
- * ```typescript
155
- * const queryBuilder = repository.createQueryBuilder('user');
156
- * addNullValueToMultipleFilter(queryBuilder, 'deletedAt');
157
- * // Results in: WHERE ... OR deletedAt IS NULL
158
- * ```
159
- */
160
- const addNullValueToMultipleFilter = (query: WhereExpressionBuilder, columnName: string): void => {
161
- query.orWhere({
162
- [columnName]: IsNull(),
163
- });
164
- };
@@ -1,36 +0,0 @@
1
- import { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
2
- import { isAliasAlreadyBusy } from './is-alias-already-busy.js';
3
-
4
- /**
5
- * Ensures an inner join is added to the TypeORM query builder only if the alias is not already in use.
6
- *
7
- * This function checks if the specified alias is already being used in the query builder.
8
- * If the alias is available, it adds an inner join with the provided entity, alias, and optional condition.
9
- * If the alias is already busy, the function returns without making any changes to the query.
10
- *
11
- * @template T - The entity type that extends ObjectLiteral
12
- * @param query - The TypeORM SelectQueryBuilder instance to add the inner join to
13
- * @param entity - The entity class (Function) or entity name (string) to join
14
- * @param alias - The alias to use for the joined entity
15
- * @param condition - Optional join condition as a string
16
- * @returns void
17
- *
18
- * @example
19
- * ```typescript
20
- * const query = repository.createQueryBuilder('user');
21
- * ensureInnerJoin(query, Profile, 'profile', 'profile.userId = user.id');
22
- * ```
23
- */
24
- export const ensureInnerJoin = <T extends ObjectLiteral>(
25
- query: SelectQueryBuilder<T>,
26
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
27
- entity: Function | string,
28
- alias: string,
29
- condition?: string,
30
- ): void => {
31
- if (isAliasAlreadyBusy(query, alias)) {
32
- return;
33
- }
34
-
35
- query.innerJoin(entity, alias, condition);
36
- };
@@ -1,36 +0,0 @@
1
- import { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
2
- import { isAliasAlreadyBusy } from './is-alias-already-busy.js';
3
-
4
- /**
5
- * Ensures a left join is added to a TypeORM query builder if the alias is not already in use.
6
- *
7
- * This function checks if the specified alias is already being used in the query.
8
- * If the alias is available, it performs a left join with the provided entity, alias, and optional condition.
9
- * If the alias is already busy, the function returns early without modifying the query.
10
- *
11
- * @template T - The entity type that extends ObjectLiteral
12
- * @param query - The TypeORM SelectQueryBuilder instance to add the left join to
13
- * @param entity - The entity class (Function) or table name (string) to join
14
- * @param alias - The alias name to use for the joined entity
15
- * @param condition - Optional join condition as a string (e.g., "alias.id = entity.foreignId")
16
- * @returns void
17
- *
18
- * @example
19
- * ```typescript
20
- * ensureLeftJoin(queryBuilder, User, 'user', 'user.id = post.userId');
21
- * ```
22
- */
23
- export const ensureLeftJoin = <T extends ObjectLiteral>(
24
- query: SelectQueryBuilder<T>,
25
-
26
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
27
- entity: Function | string,
28
- alias: string,
29
- condition?: string,
30
- ): void => {
31
- if (isAliasAlreadyBusy(query, alias)) {
32
- return;
33
- }
34
-
35
- query.leftJoin(entity, alias, condition);
36
- };
@@ -1,25 +0,0 @@
1
- import { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
2
-
3
- /**
4
- * Checks if a given alias is already used in the query builder's join attributes.
5
- *
6
- * This utility function inspects the query builder's expression map to determine
7
- * whether a specific alias name has already been assigned to any join attribute.
8
- * This is useful to avoid alias conflicts when building complex TypeORM queries.
9
- *
10
- * @template T - The entity type that extends ObjectLiteral
11
- * @param {SelectQueryBuilder<T>} query - The TypeORM SelectQueryBuilder instance to check
12
- * @param {string} alias - The alias name to search for in the join attributes
13
- * @returns {boolean} True if the alias is already used in any join attribute, false otherwise
14
- *
15
- * @example
16
- * ```typescript
17
- * const query = repository.createQueryBuilder('user');
18
- * const isBusy = isAliasAlreadyBusy(query, 'profile');
19
- * if (!isBusy) {
20
- * query.leftJoinAndSelect('user.profile', 'profile');
21
- * }
22
- * ```
23
- */
24
- export const isAliasAlreadyBusy = <T extends ObjectLiteral>(query: SelectQueryBuilder<T>, alias: string) =>
25
- query.expressionMap.joinAttributes.some((a) => a.alias.name === alias);