Compare commits
No commits in common. "58770bf89f0926b684c34ec019e8583c1673a433" and "1da2dc9c26a977a88685e25de01720fc04dd72a5" have entirely different histories.
58770bf89f
...
1da2dc9c26
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "axp-ts",
|
"name": "axp-ts",
|
||||||
"version": "1.9.7",
|
"version": "1.9.6",
|
||||||
"description": "TypeScript helper library",
|
"description": "TypeScript helper library",
|
||||||
"author": "AntoXa PRO <info@antoxa.pro>",
|
"author": "AntoXa PRO <info@antoxa.pro>",
|
||||||
"homepage": "https://antoxahub.ru/antoxa/axp-ts",
|
"homepage": "https://antoxahub.ru/antoxa/axp-ts",
|
||||||
@ -18,7 +18,7 @@
|
|||||||
"prepare": "npm run build"
|
"prepare": "npm run build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"zod": "^3.22.1"
|
"zod": "^3.21.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { TPagination } from './pagination'
|
import type { TPagination } from './pagination'
|
||||||
import type { TNotificationItem } from '../notification'
|
import type { TNotificationItem } from './notification'
|
||||||
|
|
||||||
import { Pagination } from './pagination'
|
import { Pagination } from './pagination'
|
||||||
|
|
@ -36,6 +36,8 @@ export const bFieldsSchema = {
|
|||||||
string: z
|
string: z
|
||||||
.string()
|
.string()
|
||||||
.trim()
|
.trim()
|
||||||
|
.min(2)
|
||||||
|
.max(64)
|
||||||
.describe(
|
.describe(
|
||||||
FormSchemaCtrl.toString({
|
FormSchemaCtrl.toString({
|
||||||
label: 'Строка',
|
label: 'Строка',
|
||||||
@ -77,6 +79,16 @@ export const cFieldsSchema = z.object({
|
|||||||
dateUpdate: fieldSchema(bFieldsSchema.date, {
|
dateUpdate: fieldSchema(bFieldsSchema.date, {
|
||||||
label: 'Дата изменения'
|
label: 'Дата изменения'
|
||||||
}),
|
}),
|
||||||
|
q: fieldSchema(
|
||||||
|
z.preprocess(
|
||||||
|
val => String(val).replace(regexSearch, ''),
|
||||||
|
bFieldsSchema.string
|
||||||
|
),
|
||||||
|
{
|
||||||
|
label: 'Поиск',
|
||||||
|
component: 'ui-field-search'
|
||||||
|
}
|
||||||
|
),
|
||||||
name: fieldSchema(bFieldsSchema.string, {
|
name: fieldSchema(bFieldsSchema.string, {
|
||||||
label: 'Название'
|
label: 'Название'
|
||||||
}),
|
}),
|
||||||
@ -175,23 +187,5 @@ export const cFieldsSchema = z.object({
|
|||||||
days: fieldSchema(bFieldsSchema.number.array(), {
|
days: fieldSchema(bFieldsSchema.number.array(), {
|
||||||
label: 'Дни недели',
|
label: 'Дни недели',
|
||||||
component: 'ui-picker-days'
|
component: 'ui-picker-days'
|
||||||
}),
|
})
|
||||||
q: fieldSchema(
|
|
||||||
z.preprocess(
|
|
||||||
val => String(val).replace(regexSearch, ''),
|
|
||||||
bFieldsSchema.string
|
|
||||||
),
|
|
||||||
{
|
|
||||||
label: 'Поиск',
|
|
||||||
component: 'ui-field-search'
|
|
||||||
}
|
|
||||||
),
|
|
||||||
page: fieldSchema(
|
|
||||||
z.preprocess(val => Math.abs(Number(val)), bFieldsSchema.number),
|
|
||||||
{ label: 'Страница' }
|
|
||||||
),
|
|
||||||
limit: fieldSchema(
|
|
||||||
z.preprocess(val => Math.abs(Number(val)), bFieldsSchema.number),
|
|
||||||
{ label: 'Лимит' }
|
|
||||||
)
|
|
||||||
})
|
})
|
@ -27,7 +27,7 @@ export interface IFormModel<T> {
|
|||||||
/**
|
/**
|
||||||
* Базовая модель для валидирования форм.
|
* Базовая модель для валидирования форм.
|
||||||
*/
|
*/
|
||||||
export class BaseFormModel<T extends object = {}> implements IFormModel<T> {
|
export class BaseFormModel<T extends Object = {}> implements IFormModel<T> {
|
||||||
_id: string
|
_id: string
|
||||||
|
|
||||||
dateCreate?: Date
|
dateCreate?: Date
|
@ -1,5 +1,5 @@
|
|||||||
export * from './utils'
|
|
||||||
export * from './notification'
|
|
||||||
export * from './entities'
|
export * from './entities'
|
||||||
export * from './requests'
|
export * from './form'
|
||||||
export * from './forms'
|
export * from './notification'
|
||||||
|
export * from './pagination'
|
||||||
|
export * from './data-result'
|
||||||
|
@ -7,7 +7,7 @@ export class NotificationItem implements TNotificationItem {
|
|||||||
code: string
|
code: string
|
||||||
text: string
|
text: string
|
||||||
|
|
||||||
constructor(args: { code: string; text: string }) {
|
constructor(args: {code: string, text: string }) {
|
||||||
this.code = args.code
|
this.code = args.code
|
||||||
this.text = args.text
|
this.text = args.text
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,25 @@
|
|||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { cFieldsSchema, fieldSchema } from '../forms'
|
import { cFieldsSchema, fieldSchema } from './form'
|
||||||
|
|
||||||
export const paginationSchema = cFieldsSchema
|
export const paginationSchema = z.object({
|
||||||
.pick({
|
page: fieldSchema(cFieldsSchema.shape.number, {
|
||||||
page: true,
|
label: 'Номер страницы'
|
||||||
limit: true
|
}),
|
||||||
|
limit: fieldSchema(cFieldsSchema.shape.number, {
|
||||||
|
label: 'Лимит на странице'
|
||||||
|
}),
|
||||||
|
total: fieldSchema(cFieldsSchema.shape.number, {
|
||||||
|
label: 'Общее кол-во'
|
||||||
|
}),
|
||||||
|
skip: fieldSchema(cFieldsSchema.shape.number, {
|
||||||
|
label: 'Пропустить'
|
||||||
|
}),
|
||||||
|
pages: fieldSchema(cFieldsSchema.shape.number, {
|
||||||
|
label: 'Кол-во всех страниц'
|
||||||
})
|
})
|
||||||
.extend({
|
|
||||||
total: fieldSchema(cFieldsSchema.shape.number, {
|
|
||||||
label: 'Общее кол-во'
|
|
||||||
}),
|
|
||||||
skip: fieldSchema(cFieldsSchema.shape.number, {
|
|
||||||
label: 'Пропустить'
|
|
||||||
}),
|
|
||||||
pages: fieldSchema(cFieldsSchema.shape.number, {
|
|
||||||
label: 'Кол-во всех страниц'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.describe('Пагинация')
|
|
||||||
|
|
||||||
export type TPagination = z.infer<typeof paginationSchema>
|
|
||||||
|
|
||||||
export const paginationQuerySchema = paginationSchema.pick({
|
|
||||||
page: true, limit: true
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export type TPaginationQuery = z.infer<typeof paginationQuerySchema>
|
export type TPagination = z.infer<typeof paginationSchema>
|
||||||
|
|
||||||
// Константы.
|
// Константы.
|
||||||
const DEFAULTS = { page: 1, limit: 10, maxLimit: 100 }
|
const DEFAULTS = { page: 1, limit: 10, maxLimit: 100 }
|
||||||
@ -38,11 +32,43 @@ export type TPaginationArguments = {
|
|||||||
total?: number
|
total?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Pagination implements TPagination {
|
export interface IPagination extends TPagination {
|
||||||
/**
|
/**
|
||||||
* Максимальный лимит элементов.
|
* Максимальный лимит элементов.
|
||||||
*/
|
*/
|
||||||
#maxLimit: number
|
get maxLimit(): number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Парсинг аргументов.
|
||||||
|
* @param arg - Значение аргумента для парсинга.
|
||||||
|
* @param defaultReturnValue - Возвращаемое значение по умолчанию.
|
||||||
|
* @returns Возвращает абсолютное значение числа аргумента.
|
||||||
|
*/
|
||||||
|
parseArg(
|
||||||
|
arg: number | string | undefined,
|
||||||
|
defaultReturnValue: number
|
||||||
|
): number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Присваивает значения для основных свойств класса и считает кол-во
|
||||||
|
* пропускаемых элементов в зависимости от полученных аргументов.
|
||||||
|
* @param args - Аргументы пагинации.
|
||||||
|
* @returns Возвращает текущий экземпляр класса.
|
||||||
|
*/
|
||||||
|
set(args: TPaginationArguments): this
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Возвращает простой объект пагинации.
|
||||||
|
* @returns Объект пагинации.
|
||||||
|
*/
|
||||||
|
toObject(): TPagination
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Pagination implements IPagination {
|
||||||
|
/**
|
||||||
|
* Максимальный лимит элементов.
|
||||||
|
*/
|
||||||
|
private _maxLimit: number
|
||||||
|
|
||||||
page: number = DEFAULTS.page
|
page: number = DEFAULTS.page
|
||||||
limit: number = DEFAULTS.limit
|
limit: number = DEFAULTS.limit
|
||||||
@ -63,10 +89,14 @@ export class Pagination implements TPagination {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(args: TPaginationArguments = {}, maxLimit?: number) {
|
constructor(args: TPaginationArguments = {}, maxLimit?: number) {
|
||||||
this.#maxLimit = this.parseArg(maxLimit, DEFAULTS.maxLimit)
|
this._maxLimit = this.parseArg(maxLimit, DEFAULTS.maxLimit)
|
||||||
this.set(args)
|
this.set(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get maxLimit() {
|
||||||
|
return this._maxLimit
|
||||||
|
}
|
||||||
|
|
||||||
parseArg(arg: TPaginationParseArg, defaultReturnValue: number): number {
|
parseArg(arg: TPaginationParseArg, defaultReturnValue: number): number {
|
||||||
return Pagination.parseArg(arg, defaultReturnValue)
|
return Pagination.parseArg(arg, defaultReturnValue)
|
||||||
}
|
}
|
||||||
@ -88,7 +118,7 @@ export class Pagination implements TPagination {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Проверка лимита.
|
// Проверка лимита.
|
||||||
if (this.limit > this.#maxLimit) this.limit = this.#maxLimit
|
if (this.limit > this.maxLimit) this.limit = this.maxLimit
|
||||||
|
|
||||||
// Общее кол-во.
|
// Общее кол-во.
|
||||||
if (args.total && args.total !== this.total) {
|
if (args.total && args.total !== this.total) {
|
@ -1,79 +0,0 @@
|
|||||||
import type { TPagination } from './pagination'
|
|
||||||
|
|
||||||
import { z } from 'zod'
|
|
||||||
import { isEqual } from '../utils'
|
|
||||||
import { Pagination, paginationQuerySchema } from './pagination'
|
|
||||||
import { bFieldsSchema, cFieldsSchema, fieldSchema } from '../forms'
|
|
||||||
|
|
||||||
|
|
||||||
export const querySchema = cFieldsSchema
|
|
||||||
.pick({ q: true })
|
|
||||||
.extend(paginationQuerySchema.shape)
|
|
||||||
.extend({
|
|
||||||
sort: fieldSchema(bFieldsSchema.string.min(1).max(64), {
|
|
||||||
label: 'Сортировка'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
export type TQuery = z.infer<typeof querySchema>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Объект для преобразования фильтра в URL.
|
|
||||||
*/
|
|
||||||
export type TFindFilter<T extends TQuery> = {
|
|
||||||
obj?: Omit<T, 'page' | 'limit' | 'sort'>
|
|
||||||
pagination?: TPagination
|
|
||||||
sort?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export class FindFilter<T extends TQuery> implements TFindFilter<T> {
|
|
||||||
obj?: Omit<T, 'page' | 'limit' | 'sort'>
|
|
||||||
pagination?: TPagination
|
|
||||||
sort?: string
|
|
||||||
|
|
||||||
constructor(query?: T) {
|
|
||||||
let queryCopy = Object.assign({}, query)
|
|
||||||
|
|
||||||
// Pagination.
|
|
||||||
this.setPagination(queryCopy)
|
|
||||||
for (const key of Object.keys(this.pagination)) {
|
|
||||||
if (queryCopy[key]) delete queryCopy[key]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort.
|
|
||||||
if (queryCopy.sort) {
|
|
||||||
this.sort = queryCopy.sort
|
|
||||||
delete queryCopy.sort
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obj.
|
|
||||||
this.obj = queryCopy
|
|
||||||
}
|
|
||||||
|
|
||||||
setPagination(pagination?: TPagination) {
|
|
||||||
this.pagination = new Pagination(pagination).toObject()
|
|
||||||
}
|
|
||||||
|
|
||||||
static getQuery <T extends TQuery = {}>(filter: TFindFilter<T>): T {
|
|
||||||
let query: any = {}
|
|
||||||
for(const key of Object.keys(filter.obj)) {
|
|
||||||
query[key] = filter.obj[key]
|
|
||||||
}
|
|
||||||
if (filter.pagination?.page) query.page = filter.pagination.page
|
|
||||||
if (filter.pagination?.limit) query.limit = filter.pagination.limit
|
|
||||||
if (filter.sort) query.sort = filter.sort
|
|
||||||
return query
|
|
||||||
}
|
|
||||||
|
|
||||||
toObject(): TFindFilter<T> {
|
|
||||||
return {
|
|
||||||
obj: this.obj,
|
|
||||||
pagination: this.pagination,
|
|
||||||
sort: this.sort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isEqual(filters: TFindFilter<T>[]) {
|
|
||||||
return isEqual([this, ...filters])
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
export * from './pagination'
|
|
||||||
export * from './data-result'
|
|
||||||
export * from './find-filter'
|
|
@ -1 +0,0 @@
|
|||||||
export * from './objects'
|
|
@ -1,28 +0,0 @@
|
|||||||
export const isEqual = <T extends object>(objects: T[]) => {
|
|
||||||
for (let i = 0; i < objects.length; i++) {
|
|
||||||
const obj1 = objects[i]
|
|
||||||
const obj2 = objects[i + 1]
|
|
||||||
if (obj2) {
|
|
||||||
const keys1 = Object.keys(obj1)
|
|
||||||
const keys2 = Object.keys(obj2)
|
|
||||||
|
|
||||||
if (keys1.length !== keys2.length) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for(const key of keys1) {
|
|
||||||
if (typeof obj1[key] !== 'object') {
|
|
||||||
if (obj1[key] !== obj2[key]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!isEqual([obj1[key], obj2[key]])) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user