-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: organize config, validation, decorators (#8118)
* refactor: validation * refactor: utilities * refactor: config
- Loading branch information
Showing
119 changed files
with
666 additions
and
684 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import { SetMetadata } from '@nestjs/common'; | ||
import _ from 'lodash'; | ||
import { setUnion } from 'src/utils'; | ||
|
||
// PostgreSQL uses a 16-bit integer to indicate the number of bound parameters. This means that the | ||
// maximum number of parameters is 65535. Any query that tries to bind more than that (e.g. searching | ||
// by a list of IDs) requires splitting the query into multiple chunks. | ||
// We are rounding down this limit, as queries commonly include other filters and parameters. | ||
export const DATABASE_PARAMETER_CHUNK_SIZE = 65_500; | ||
|
||
/** | ||
* Chunks an array or set into smaller collections of the same type and specified size. | ||
* | ||
* @param collection The collection to chunk. | ||
* @param size The size of each chunk. | ||
*/ | ||
function chunks<T>(collection: Array<T>, size: number): Array<Array<T>>; | ||
function chunks<T>(collection: Set<T>, size: number): Array<Set<T>>; | ||
function chunks<T>(collection: Array<T> | Set<T>, size: number): Array<Array<T>> | Array<Set<T>> { | ||
if (collection instanceof Set) { | ||
const result = []; | ||
let chunk = new Set<T>(); | ||
for (const element of collection) { | ||
chunk.add(element); | ||
if (chunk.size === size) { | ||
result.push(chunk); | ||
chunk = new Set<T>(); | ||
} | ||
} | ||
if (chunk.size > 0) { | ||
result.push(chunk); | ||
} | ||
return result; | ||
} else { | ||
return _.chunk(collection, size); | ||
} | ||
} | ||
|
||
/** | ||
* Wraps a method that takes a collection of parameters and sequentially calls it with chunks of the collection, | ||
* to overcome the maximum number of parameters allowed by the database driver. | ||
* | ||
* @param options.paramIndex The index of the function parameter to chunk. Defaults to 0. | ||
* @param options.flatten Whether to flatten the results. Defaults to false. | ||
*/ | ||
export function Chunked(options: { paramIndex?: number; mergeFn?: (results: any) => any } = {}): MethodDecorator { | ||
return (target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) => { | ||
const originalMethod = descriptor.value; | ||
const parameterIndex = options.paramIndex ?? 0; | ||
descriptor.value = async function (...arguments_: any[]) { | ||
const argument = arguments_[parameterIndex]; | ||
|
||
// Early return if argument length is less than or equal to the chunk size. | ||
if ( | ||
(Array.isArray(argument) && argument.length <= DATABASE_PARAMETER_CHUNK_SIZE) || | ||
(argument instanceof Set && argument.size <= DATABASE_PARAMETER_CHUNK_SIZE) | ||
) { | ||
return await originalMethod.apply(this, arguments_); | ||
} | ||
|
||
return Promise.all( | ||
chunks(argument, DATABASE_PARAMETER_CHUNK_SIZE).map(async (chunk) => { | ||
await Reflect.apply(originalMethod, this, [ | ||
...arguments_.slice(0, parameterIndex), | ||
chunk, | ||
...arguments_.slice(parameterIndex + 1), | ||
]); | ||
}), | ||
).then((results) => (options.mergeFn ? options.mergeFn(results) : results)); | ||
}; | ||
}; | ||
} | ||
|
||
export function ChunkedArray(options?: { paramIndex?: number }): MethodDecorator { | ||
return Chunked({ ...options, mergeFn: _.flatten }); | ||
} | ||
|
||
export function ChunkedSet(options?: { paramIndex?: number }): MethodDecorator { | ||
return Chunked({ ...options, mergeFn: setUnion }); | ||
} | ||
|
||
// https://stackoverflow.com/a/74898678 | ||
export function DecorateAll( | ||
decorator: <T>( | ||
target: any, | ||
propertyKey: string, | ||
descriptor: TypedPropertyDescriptor<T>, | ||
) => TypedPropertyDescriptor<T> | void, | ||
) { | ||
return (target: any) => { | ||
const descriptors = Object.getOwnPropertyDescriptors(target.prototype); | ||
for (const [propName, descriptor] of Object.entries(descriptors)) { | ||
const isMethod = typeof descriptor.value == 'function' && propName !== 'constructor'; | ||
if (!isMethod) { | ||
continue; | ||
} | ||
decorator({ ...target, constructor: { ...target.constructor, name: target.name } as any }, propName, descriptor); | ||
Object.defineProperty(target.prototype, propName, descriptor); | ||
} | ||
}; | ||
} | ||
|
||
const UUID = '00000000-0000-4000-a000-000000000000'; | ||
|
||
export const DummyValue = { | ||
UUID, | ||
UUID_SET: new Set([UUID]), | ||
PAGINATION: { take: 10, skip: 0 }, | ||
EMAIL: '[email protected]', | ||
STRING: 'abcdefghi', | ||
BUFFER: Buffer.from('abcdefghi'), | ||
DATE: new Date(), | ||
TIME_BUCKET: '2024-01-01T00:00:00.000Z', | ||
}; | ||
|
||
export const GENERATE_SQL_KEY = 'generate-sql-key'; | ||
|
||
export interface GenerateSqlQueries { | ||
name?: string; | ||
params: unknown[]; | ||
} | ||
|
||
/** Decorator to enable versioning/tracking of generated Sql */ | ||
export const GenerateSql = (...options: GenerateSqlQueries[]) => SetMetadata(GENERATE_SQL_KEY, options); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.