Comparing version 48.2.0 to 49.0.0
@@ -1,2 +0,2 @@ | ||
import { KmoreQueryBuilder, PageArrayType } from './builder.types.js'; | ||
import { KmoreQueryBuilder, PageRawType, PageWrapType } from './builder.types.js'; | ||
import { CaseType, EventCallbacks, KmoreTransaction, KmoreTransactionConfig, QueryContext, TrxIdQueryMap } from './types.js'; | ||
@@ -52,4 +52,4 @@ export declare abstract class KmoreBase<Context = any> { | ||
} | ||
declare type ResultPagerHandler<T = unknown> = (options: PagerOptions, proxyCreator: (options: ProxyGetOptions) => KmoreQueryBuilder) => Promise<PageArrayType<T> | undefined>; | ||
declare type ResultPagerHandler<T = unknown> = (options: PagerOptions, proxyCreator: (options: ProxyGetOptions) => KmoreQueryBuilder) => Promise<PageRawType<T> | PageWrapType<T> | undefined>; | ||
export {}; | ||
//# sourceMappingURL=base.d.ts.map |
import type { PagerOptions, ProxyGetOptions } from './base.js'; | ||
import type { KmoreQueryBuilder, PageArrayType } from './builder.types.js'; | ||
export declare function pager<T = unknown>(options: PagerOptions, proxyCreator: (options: ProxyGetOptions) => KmoreQueryBuilder): Promise<PageArrayType<T> | undefined>; | ||
import type { KmoreQueryBuilder, PageRawType, PageWrapType } from './builder.types.js'; | ||
export declare function pager<T = unknown>(options: PagerOptions, proxyCreator: (options: ProxyGetOptions) => KmoreQueryBuilder): Promise<PageRawType<T> | PageWrapType<T> | undefined>; | ||
//# sourceMappingURL=builder.auto-paging.d.ts.map |
@@ -6,2 +6,3 @@ import assert from 'node:assert'; | ||
import { builderApplyTransactingProxy } from './proxy.apply.js'; | ||
import { initPageTypeMaping } from './proxy.auto-paging.js'; | ||
import { proxyGetThen } from './proxy.get.then.js'; | ||
@@ -15,8 +16,20 @@ import { extRefTableFnPropertySmartJoin } from './smart-join.js'; | ||
const props = { | ||
pageCountAll: total, | ||
pageCurrent: +pagingOptions.page, | ||
total, | ||
page: +pagingOptions.page, | ||
pageSize: +pagingOptions.pageSize, | ||
}; | ||
const outputMaping = pagingOptions.wrapOutput === true | ||
? { ...initPageTypeMaping } | ||
: void 0; | ||
if (!total || !builderPager) { | ||
return addPaginMetaOnArray([], props); | ||
if (outputMaping) { | ||
const data = { | ||
...props, | ||
rows: [], | ||
}; | ||
return data; | ||
} | ||
else { | ||
return addPaginMetaOnArray([], props); | ||
} | ||
} | ||
@@ -31,4 +44,28 @@ // const builderPagerPatched = createQueryBuilderGetProxy(kmore, builderPager) | ||
// console.info({ builderPageSql: builderPagerSql }) | ||
return builderPagerPatched.then((rows) => addPaginMetaOnArray(rows, props)); | ||
return pagingOptions.wrapOutput | ||
? builderPagerPatched.then((rows) => genOutputData(rows, props, outputMaping)) | ||
: builderPagerPatched.then((rows) => addPaginMetaOnArray(rows, props)); | ||
} | ||
function genOutputData(input, props, outputMaping) { | ||
assert(outputMaping, 'outputMaping should be set'); | ||
assert(Object.keys(outputMaping).length, 'outputMaping should not be empty'); | ||
const data = { | ||
...props, | ||
rows: input ?? [], | ||
}; | ||
if (outputMaping) { | ||
Object.entries(outputMaping).forEach(([key, key2]) => { | ||
if (!Object.hasOwn(props, key)) { | ||
return; | ||
} | ||
// @ts-ignore | ||
const value = props[key]; | ||
Object.defineProperty(data, key2, { | ||
...defaultPropDescriptor, | ||
value, | ||
}); | ||
}); | ||
} | ||
return data; | ||
} | ||
function addPaginMetaOnArray(input, props) { | ||
@@ -35,0 +72,0 @@ if (!Array.isArray(input)) { |
import { CaseConvertTable, CaseType, DbScopedColsByKey, DbScopedColsByTableType, JoinTableWithCaseConvert, SplitScopedColumn, StrKey, UnwrapArrayMember } from '@waiting/shared-types'; | ||
import { DbDict } from 'kmore-types'; | ||
import type { Knex } from 'knex'; | ||
export declare type KmoreQueryBuilder<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends boolean = false, TRecord extends {} = any, TResult = any> = QueryBuilderExtName<D> & QueryBuilderExtMethod<D, CaseConvert, IsEnabled<EnablePage>, TRecord> & QueryBuilder<D, CaseConvert, IsEnabled<EnablePage>, TRecord, AddPagingMeta<TResult, IsEnabled<EnablePage>>>; | ||
/** | ||
* - 0: No paging | ||
* - 1: Paging, PagingMeta on response Array | ||
* - 2: paging, wrap response as `PageWrapType` | ||
*/ | ||
declare type PagingCategory = 0 | 1 | 2; | ||
export declare type KmoreQueryBuilder<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends PagingCategory = 0, TRecord extends {} = any, TResult = any> = QueryBuilderExtName<D> & QueryBuilderExtMethod<D, CaseConvert, EnablePage, TRecord> & QueryBuilder<D, CaseConvert, EnablePage, TRecord, AddPagingMeta<TResult, EnablePage>>; | ||
declare type OmitQueryBuilderKeys = 'select' | 'where' | 'orderBy' | keyof Knex.ChainableInterface; | ||
interface QueryBuilder<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends boolean = false, TRecord extends {} = any, TResult = any> extends Knex.ChainableInterface<AddPagingMeta<ResolveResult<TResult>, EnablePage>>, Omit<Knex.QueryBuilder<TRecord, TResult>, OmitQueryBuilderKeys> { | ||
interface QueryBuilder<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends PagingCategory = 0, TRecord extends {} = any, TResult = any> extends Knex.ChainableInterface<AddPagingMeta<ResolveResult<TResult>, EnablePage>>, Omit<Knex.QueryBuilder<TRecord, TResult>, OmitQueryBuilderKeys> { | ||
select: Select<D, CaseConvert, EnablePage, TRecord, TResult>; | ||
@@ -14,3 +20,3 @@ where: Where<D, CaseConvert, EnablePage, TRecord, TResult>; | ||
}; | ||
export declare type TbQueryBuilder<D extends {}, CaseConvert extends CaseType, TRecord extends {}, Context> = (ctx?: Context) => KmoreQueryBuilder<D, CaseConvert, false, TRecord, TRecord[]>; | ||
export declare type TbQueryBuilder<D extends {}, CaseConvert extends CaseType, TRecord extends {}, Context> = (ctx?: Context) => KmoreQueryBuilder<D, CaseConvert, 0, TRecord, TRecord[]>; | ||
interface QueryBuilderExtName<D extends {} = {}> { | ||
@@ -23,3 +29,3 @@ caseConvert: CaseType; | ||
} | ||
interface QueryBuilderExtMethod<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends boolean = false, TRecord extends {} = any> { | ||
interface QueryBuilderExtMethod<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends PagingCategory = 0, TRecord extends {} = any> { | ||
smartCrossJoin: SmartJoin<D, CaseConvert, EnablePage, TRecord>; | ||
@@ -32,4 +38,7 @@ smartInnerJoin: SmartJoin<D, CaseConvert, EnablePage, TRecord>; | ||
} | ||
declare type AutoPaging<D extends {} = {}, CaseConvert extends CaseType = CaseType, TRecord extends {} = any> = (options?: Partial<PagingOptions>) => KmoreQueryBuilder<D, CaseConvert, true, TRecord, TRecord[]>; | ||
declare type SmartJoin<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends boolean = false, TResult = unknown[]> = <TRecord1 = UnwrapArrayMember<TResult>, C2 extends DbScopedColsByKey<D> = DbScopedColsByKey<D>, C1 extends DbScopedColsByKey<D> = DbScopedColsByTableType<D, TRecord1>, TTable2 extends StrKey<D> = SplitScopedColumn<D, C2>[0], TRecord2 extends D[TTable2] = D[TTable2], TResult2 = JoinTableWithCaseConvert<TRecord1, TRecord2 extends any ? D[TTable2] : TRecord2, TTable2, CaseConvert>>( | ||
declare type AutoPaging<D extends {} = {}, CaseConvert extends CaseType = CaseType, TRecord extends {} = any> = <Wrap extends boolean | undefined = false>(options?: Partial<PagingOptions>, wrapOutput?: Wrap) => KmoreQueryBuilder<D, CaseConvert, CalcPagingCat<Wrap>, TRecord, TRecord[]>; | ||
declare type CalcPagingCat<T> = T extends true ? 2 : 1; | ||
declare type AddPagingMeta<TSelection, EnablePage extends PagingCategory = 0> = EnablePage extends 0 ? TSelection : TSelection extends (infer R)[] ? EnablePage extends 2 ? WrapPageOutput<R> : PageRawType<R> : TSelection; | ||
declare type WrapPageOutput<T> = T extends PageWrapType ? T : PageWrapType<T>; | ||
declare type SmartJoin<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends PagingCategory = 0, TResult = unknown[]> = <TRecord1 = UnwrapArrayMember<TResult>, C2 extends DbScopedColsByKey<D> = DbScopedColsByKey<D>, C1 extends DbScopedColsByKey<D> = DbScopedColsByTableType<D, TRecord1>, TTable2 extends StrKey<D> = SplitScopedColumn<D, C2>[0], TRecord2 extends D[TTable2] = D[TTable2], TResult2 = JoinTableWithCaseConvert<TRecord1, TRecord2 extends any ? D[TTable2] : TRecord2, TTable2, CaseConvert>>( | ||
/** | ||
@@ -63,7 +72,6 @@ * scoped column name, e.g. 'tb_name.col_name', | ||
*/ | ||
export declare type PageArrayType<T = unknown> = T[] & PagingMeta; | ||
/** | ||
* Note: keyof PagingMeta is not enumerable | ||
*/ | ||
export declare type PageDataType<T = {}> = T & PagingMeta; | ||
export declare type PageRawType<T = unknown> = T[] & PagingMeta; | ||
export interface PageWrapType<T = unknown> extends PagingMeta { | ||
rows: T[]; | ||
} | ||
export interface PagingMeta { | ||
@@ -77,7 +85,7 @@ /** | ||
*/ | ||
pageCountAll: number; | ||
total: number; | ||
/** | ||
* Current page number, start from 1 | ||
*/ | ||
pageCurrent: number; | ||
page: number; | ||
/** | ||
@@ -89,5 +97,3 @@ * Number of rows of each page. | ||
} | ||
declare type AddPagingMeta<TSelection, EnablePage extends boolean = false> = EnablePage extends false ? RemovePagingMeta<TSelection> : TSelection extends unknown[] ? PageDataType<RemovePagingMeta<TSelection>> : TSelection; | ||
declare type RemovePagingMeta<T> = T extends ((infer M)[] & PagingMeta) ? M[] : T; | ||
interface Select<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends boolean = false, TRecord extends {} = any, TResult = unknown[]> extends AliasQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult>, ColumnNameQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult> { | ||
interface Select<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends PagingCategory = 0, TRecord extends {} = any, TResult = unknown[]> extends AliasQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult>, ColumnNameQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult> { | ||
(): KmoreQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult>; | ||
@@ -97,3 +103,3 @@ <TResult2 = ArrayIfAlready<TResult, any>, TInnerRecord extends {} = any, TInnerResult = any>(...subQueryBuilders: readonly KmoreQueryBuilder<D, CaseConvert, EnablePage, TInnerRecord, TInnerResult>[]): KmoreQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult2>; | ||
} | ||
interface AliasQueryBuilder<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends boolean = false, TRecord extends {} = any, TResult = unknown[]> { | ||
interface AliasQueryBuilder<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends PagingCategory = 0, TRecord extends {} = any, TResult = unknown[]> { | ||
<AliasUT extends Knex.InferrableColumnDescriptor<Knex.ResolveTableType<TRecord>>[], TResult2 = ArrayIfAlready<TResult, DeferredKeySelectionNS.Augment<UnwrapArrayMember<TResult>, Knex.ResolveTableType<TRecord>, IncompatibleToAlt<ArrayMember<AliasUT>, string, never>, Knex.IntersectAliases<AliasUT>>>>(...aliases: AliasUT): KmoreQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult2>; | ||
@@ -104,3 +110,3 @@ <AliasUT extends Knex.InferrableColumnDescriptor<Knex.ResolveTableType<TRecord>>[], TResult2 = ArrayIfAlready<TResult, DeferredKeySelectionNS.Augment<UnwrapArrayMember<TResult>, Knex.ResolveTableType<TRecord>, IncompatibleToAlt<ArrayMember<AliasUT>, string, never>, Knex.IntersectAliases<AliasUT>>>>(aliases: AliasUT): KmoreQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult2>; | ||
} | ||
interface ColumnNameQueryBuilder<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends boolean = false, TRecord extends {} = any, TResult = unknown[]> { | ||
interface ColumnNameQueryBuilder<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends PagingCategory = 0, TRecord extends {} = any, TResult = unknown[]> { | ||
(columnName: '*'): KmoreQueryBuilder<D, CaseConvert, EnablePage, TRecord, ArrayIfAlready<TResult, DeferredKeySelection<TRecord, string>>>; | ||
@@ -112,3 +118,3 @@ <ColNameUT extends keyof Knex.ResolveTableType<TRecord>, TResult2 = DeferredKeySelectionNS.Augment<UnwrapArrayMember<TResult>, Knex.ResolveTableType<TRecord>, ColNameUT & string>[]>(...columnNames: readonly ColNameUT[]): KmoreQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult2>; | ||
} | ||
interface OrderBy<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends boolean = false, TRecord extends {} = any, TResult = unknown[]> { | ||
interface OrderBy<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends PagingCategory = 0, TRecord extends {} = any, TResult = unknown[]> { | ||
(columnName: keyof TRecord | QueryBuilder, order?: 'asc' | 'desc', nulls?: 'first' | 'last'): KmoreQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult>; | ||
@@ -135,3 +141,2 @@ (columnName: string | QueryBuilder, order?: string, nulls?: string): KmoreQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult>; | ||
declare type IncompatibleToAlt<T, TBase, TAlt> = T extends TBase ? T : TAlt; | ||
declare type IsEnabled<T extends boolean> = T extends true ? true : false; | ||
declare type MappedAliasType<TBase, TAliasMapping> = {} & { | ||
@@ -171,5 +176,5 @@ [K in keyof TAliasMapping]: TAliasMapping[K] extends keyof TBase ? TBase[TAliasMapping[K]] : any; | ||
} | ||
declare type ResolveResult<S, EnablePage extends boolean = false> = AddPagingMeta<DeferredKeySelectionNS.Resolve<S>, EnablePage>; | ||
declare type ResolveResult<S, EnablePage extends PagingCategory = 0> = AddPagingMeta<DeferredKeySelectionNS.Resolve<S>, EnablePage>; | ||
declare type ComparisonOperator = '=' | '>' | '>=' | '<' | '<=' | '<>'; | ||
export interface Where<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends boolean = false, TRecord extends {} = any, TResult = any> extends WhereRaw<D, CaseConvert, EnablePage, TRecord, TResult> { | ||
export interface Where<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends PagingCategory = 0, TRecord extends {} = any, TResult = any> extends WhereRaw<D, CaseConvert, EnablePage, TRecord, TResult> { | ||
(raw: Knex.Raw): KmoreQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult>; | ||
@@ -188,3 +193,3 @@ (callback: Knex.QueryCallback<TRecord, TResult>): KmoreQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult>; | ||
} | ||
interface WhereRaw<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends boolean = false, TRecord extends {} = any, TResult = unknown[]> extends Knex.RawQueryBuilder<TRecord, TResult> { | ||
interface WhereRaw<D extends {} = {}, CaseConvert extends CaseType = CaseType, EnablePage extends PagingCategory = 0, TRecord extends {} = any, TResult = unknown[]> extends Knex.RawQueryBuilder<TRecord, TResult> { | ||
(condition: boolean): KmoreQueryBuilder<D, CaseConvert, EnablePage, TRecord, TResult>; | ||
@@ -191,0 +196,0 @@ } |
@@ -1,5 +0,9 @@ | ||
import { KmoreQueryBuilder, PagingMeta, PagingOptions } from './builder.types.js'; | ||
export declare const initPagingOptions: PagingOptions; | ||
import { KmoreQueryBuilder, PageWrapType, PagingMeta, PagingOptions } from './builder.types.js'; | ||
export declare const initPagingOptions: _PagingOptions; | ||
export declare const initPagingMeta: PagingMeta; | ||
export declare const initPageTypeMaping: Record<keyof PageWrapType, string>; | ||
export interface _PagingOptions extends PagingOptions { | ||
wrapOutput: boolean; | ||
} | ||
export declare function extRefTableFnPropertyAutoPaging(refTable: KmoreQueryBuilder): KmoreQueryBuilder; | ||
//# sourceMappingURL=proxy.auto-paging.d.ts.map |
@@ -8,8 +8,15 @@ import assert from 'assert'; | ||
pageSize: 10, | ||
wrapOutput: false, | ||
}; | ||
export const initPagingMeta = { | ||
pageCountAll: 0, | ||
pageCurrent: 1, | ||
total: 0, | ||
page: 1, | ||
pageSize: initPagingOptions.pageSize, | ||
}; | ||
export const initPageTypeMaping = { | ||
total: 'total', | ||
page: 'page', | ||
pageSize: 'pageSize', | ||
rows: 'rows', | ||
}; | ||
export function extRefTableFnPropertyAutoPaging(refTable) { | ||
@@ -20,7 +27,7 @@ assert(typeof refTable[KmorePageKey.AutoPaging] !== 'function', 'extRefTableFnPropertyAutoPaging() can only be called once'); | ||
writable: true, | ||
value: (options) => autoPagingBuilder(options, refTable), | ||
value: (options, wrapOutput) => autoPagingBuilder(options, wrapOutput ?? false, refTable), | ||
}); | ||
return refTable; | ||
} | ||
function autoPagingBuilder(options, queryBuilder) { | ||
function autoPagingBuilder(options, wrapOutput, queryBuilder) { | ||
if (Object.hasOwn(queryBuilder, KmorePageKey.PagingOptions)) { | ||
@@ -33,2 +40,5 @@ throw new Error('autoPaging() can only be called once'); | ||
}; | ||
if (wrapOutput === true) { | ||
opts.wrapOutput = true; | ||
} | ||
assert(opts.page > 0, 'AutoPagingOptions page should be greater than 0'); | ||
@@ -35,0 +45,0 @@ assert(opts.pageSize > 0, 'AutoPagingOptions pageSize should be greater than 0'); |
@@ -20,2 +20,3 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
&& !Object.hasOwn(target, KmorePageKey.PagingProcessed)) { | ||
// pager() | ||
getThenProxyRet = resultPagerHandler({ builder: target, kmore }, createQueryBuilderGetProxy); | ||
@@ -22,0 +23,0 @@ } |
{ | ||
"name": "kmore", | ||
"author": "waiting", | ||
"version": "48.2.0", | ||
"version": "49.0.0", | ||
"description": "A SQL query builder based on knex with powerful TypeScript type support", | ||
@@ -46,4 +46,4 @@ "keywords": [ | ||
"cross-env": "7", | ||
"kmore-cli": "^48.2.0", | ||
"kmore-types": "^48.2.0", | ||
"kmore-cli": "^49.0.0", | ||
"kmore-types": "^49.0.0", | ||
"knex": "^2.3.0", | ||
@@ -82,3 +82,3 @@ "pg": "^8.7.3" | ||
}, | ||
"gitHead": "38a244f257542f1d3925ab58f6957a9d27cceaa6" | ||
"gitHead": "ec2a9acdbea2f624f7643520a2529a815b751a02" | ||
} |
@@ -184,15 +184,43 @@ # [kmore](https://waitingsong.github.io/kmore/) | ||
``` | ||
const options: Partial<PagingOptions> = { | ||
page: 2, // default 1 | ||
pageSize: 20, // default 10 | ||
} | ||
const users = await tables.ref_tb_user().autoPaging(options) | ||
assert(Array.isArray(users)) | ||
assert(users.length) | ||
- RawType: | ||
// not enumerable properties of pager | ||
const { pageCountAll, pageCurrent, pageSize } = users | ||
``` | ||
```ts | ||
const options: Partial<PagingOptions> = { | ||
page: 2, // default 1 | ||
pageSize: 20, // default 10 | ||
} | ||
const users = await tables.ref_tb_user().autoPaging(options) | ||
assert(Array.isArray(users)) | ||
assert(users.length) | ||
// not enumerable properties of pager | ||
const { | ||
total, // total records | ||
page, // current page number, start from 1 | ||
pageSize, // size of items each page | ||
} = users | ||
``` | ||
- WrapType: | ||
```ts | ||
const options: Partial<PagingOptions> = { | ||
page: 2, // default 1 | ||
pageSize: 20, // default 10 | ||
} | ||
const users = await tables.ref_tb_user().autoPaging(options, true) | ||
assert(! Array.isArray(users)) | ||
assert(Array.isArray(users.rows)) | ||
assert(users.rows.length) | ||
// enumerable properties of pager | ||
const { | ||
total, // total records | ||
page, // current page number, start from 1 | ||
pageSize, // size of items each page | ||
rows, // response records | ||
} = users | ||
``` | ||
More examples of auto paging see [auto-paing](https://github.com/waitingsong/kmore/blob/main/packages/kmore/test/auto-paging/) | ||
@@ -286,7 +314,7 @@ | ||
| Package | Version | | ||
| -------------------------- | ------------------------ | | ||
| [`kmore`] | [![kmore-svg]][kmore-ch] | | ||
| [`kmore-types`] | [![types-svg]][types-ch] | | ||
| [`kmore-cli`] | [![cli-svg]][cli-ch] | | ||
| Package | Version | | ||
| --------------- | ------------------------ | | ||
| [`kmore`] | [![kmore-svg]][kmore-ch] | | ||
| [`kmore-types`] | [![types-svg]][types-ch] | | ||
| [`kmore-cli`] | [![cli-svg]][cli-ch] | | ||
| [`@mwcp/kmore`] | [![mw-svg]][mw-ch] | | ||
@@ -293,0 +321,0 @@ |
@@ -183,15 +183,43 @@ # [kmore](https://waitingsong.github.io/kmore/) | ||
``` | ||
const options: Partial<PagingOptions> = { | ||
page: 2, // default 1 | ||
pageSize: 20, // default 10 | ||
} | ||
const users = await tables.ref_tb_user().autoPaging(options) | ||
assert(Array.isArray(users)) | ||
assert(users.length) | ||
- RawType: | ||
// 不可枚举分页属性 | ||
const { pageCountAll, pageCurrent, pageSize } = users | ||
``` | ||
```ts | ||
const options: Partial<PagingOptions> = { | ||
page: 2, // default 1 | ||
pageSize: 20, // default 10 | ||
} | ||
const users = await tables.ref_tb_user().autoPaging(options) | ||
assert(Array.isArray(users)) | ||
assert(users.length) | ||
// 不可枚举分页属性 | ||
const { | ||
total, // 总记录数 | ||
page, // 当前页号,起始 1 | ||
pageSize, // 每页记录数 | ||
} = users | ||
``` | ||
- WrapType: | ||
```ts | ||
const options: Partial<PagingOptions> = { | ||
page: 2, // default 1 | ||
pageSize: 20, // default 10 | ||
} | ||
const users = await tables.ref_tb_user().autoPaging(options, true) | ||
assert(! Array.isArray(users)) | ||
assert(Array.isArray(users.rows)) | ||
assert(users.rows.length) | ||
// 可枚举分页属性 | ||
const { | ||
total, // 总记录数 | ||
page, // 当前页号,起始 1 | ||
pageSize, // 每页记录数 | ||
rows, // 查询结果数据 | ||
} = users | ||
``` | ||
More examples of auto paging see [auto-paing](https://github.com/waitingsong/kmore/blob/main/packages/kmore/test/auto-paging/) | ||
@@ -285,7 +313,7 @@ | ||
| Package | Version | | ||
| -------------------------- | ------------------------ | | ||
| [`kmore`] | [![kmore-svg]][kmore-ch] | | ||
| [`kmore-types`] | [![types-svg]][types-ch] | | ||
| [`kmore-cli`] | [![cli-svg]][cli-ch] | | ||
| Package | Version | | ||
| --------------- | ------------------------ | | ||
| [`kmore`] | [![kmore-svg]][kmore-ch] | | ||
| [`kmore-types`] | [![types-svg]][types-ch] | | ||
| [`kmore-cli`] | [![cli-svg]][cli-ch] | | ||
| [`@mwcp/kmore`] | [![mw-svg]][mw-ch] | | ||
@@ -292,0 +320,0 @@ |
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
import { KmoreQueryBuilder, PageArrayType } from './builder.types.js' | ||
import { KmoreQueryBuilder, PageRawType, PageWrapType } from './builder.types.js' | ||
import { | ||
@@ -94,3 +94,3 @@ CaseType, | ||
proxyCreator: (options: ProxyGetOptions) => KmoreQueryBuilder, | ||
) => Promise<PageArrayType<T> | undefined> | ||
) => Promise<PageRawType<T> | PageWrapType<T> | undefined> | ||
@@ -7,9 +7,10 @@ import assert from 'node:assert' | ||
import type { | ||
PagingOptions, | ||
KmoreQueryBuilder, | ||
PageArrayType, | ||
PageRawType, | ||
PagingMeta, | ||
PageWrapType, | ||
} from './builder.types.js' | ||
import { defaultPropDescriptor } from './config.js' | ||
import { builderApplyTransactingProxy } from './proxy.apply.js' | ||
import { initPageTypeMaping, _PagingOptions } from './proxy.auto-paging.js' | ||
import { proxyGetThen } from './proxy.get.then.js' | ||
@@ -24,3 +25,3 @@ import { extRefTableFnPropertySmartJoin } from './smart-join.js' | ||
proxyCreator: (options: ProxyGetOptions) => KmoreQueryBuilder, | ||
): Promise<PageArrayType<T> | undefined> { | ||
): Promise<PageRawType<T> | PageWrapType<T> | undefined> { | ||
@@ -32,9 +33,23 @@ const { kmore } = options | ||
const props: PagingMeta = { | ||
pageCountAll: total, | ||
pageCurrent: +pagingOptions.page, | ||
total, | ||
page: +pagingOptions.page, | ||
pageSize: +pagingOptions.pageSize, | ||
} | ||
const outputMaping = pagingOptions.wrapOutput === true | ||
? { ...initPageTypeMaping } | ||
: void 0 | ||
if (! total || ! builderPager) { | ||
return addPaginMetaOnArray([], props) | ||
if (outputMaping) { | ||
const data: PageWrapType<T> = { | ||
...props, | ||
rows: [], | ||
} | ||
return data | ||
} | ||
else { | ||
return addPaginMetaOnArray([], props) | ||
} | ||
} | ||
@@ -52,9 +67,41 @@ | ||
return builderPagerPatched.then((rows: T[] | undefined) => addPaginMetaOnArray(rows, props)) | ||
return pagingOptions.wrapOutput | ||
? builderPagerPatched.then((rows: T[] | undefined) => genOutputData(rows, props, outputMaping)) | ||
: builderPagerPatched.then((rows: T[] | undefined) => addPaginMetaOnArray(rows, props)) | ||
} | ||
function genOutputData<T = unknown>( | ||
input: T[] | undefined, | ||
props: PagingMeta, | ||
outputMaping: Record<keyof PageWrapType, string> | undefined, | ||
): PageWrapType<T> { | ||
assert(outputMaping, 'outputMaping should be set') | ||
assert(Object.keys(outputMaping).length, 'outputMaping should not be empty') | ||
const data: PageWrapType<T> = { | ||
...props, | ||
rows: input ?? [], | ||
} | ||
if (outputMaping) { | ||
Object.entries(outputMaping).forEach(([key, key2]) => { | ||
if (! Object.hasOwn(props, key)) { return } | ||
// @ts-ignore | ||
const value = props[key] as unknown | ||
Object.defineProperty(data, key2, { | ||
...defaultPropDescriptor, | ||
value, | ||
}) | ||
}) | ||
} | ||
return data | ||
} | ||
function addPaginMetaOnArray<T = unknown>( | ||
input: T[] | undefined, | ||
props: PagingMeta, | ||
): PageArrayType<T> | undefined { | ||
): PageRawType<T> | undefined { | ||
@@ -70,3 +117,3 @@ if (! Array.isArray(input)) { return } | ||
}) | ||
return input as PageArrayType<T> | ||
return input as PageRawType<T> | ||
} | ||
@@ -76,3 +123,3 @@ | ||
total: number | ||
pagingOptions: PagingOptions | ||
pagingOptions: _PagingOptions | ||
builderPager?: KmoreQueryBuilder | undefined | ||
@@ -99,3 +146,3 @@ } | ||
// @ts-ignore | ||
const pagingOptions: PagingOptions = builder[KmorePageKey.PagingOptions] | ||
const pagingOptions: _PagingOptions = builder[KmorePageKey.PagingOptions] | ||
assert(pagingOptions, 'pagingOptions should be set') | ||
@@ -102,0 +149,0 @@ void Object.defineProperty(builder, KmorePageKey.PagingProcessed, { |
@@ -19,11 +19,18 @@ /* eslint-disable max-len */ | ||
/** | ||
* - 0: No paging | ||
* - 1: Paging, PagingMeta on response Array | ||
* - 2: paging, wrap response as `PageWrapType` | ||
*/ | ||
type PagingCategory = 0 | 1 | 2 | ||
export type KmoreQueryBuilder< | ||
D extends {} = {}, | ||
CaseConvert extends CaseType = CaseType, | ||
EnablePage extends boolean = false, | ||
EnablePage extends PagingCategory = 0, | ||
TRecord extends {} = any, | ||
TResult = any | ||
> = QueryBuilderExtName<D> | ||
& QueryBuilderExtMethod<D, CaseConvert, IsEnabled<EnablePage>, TRecord> | ||
& QueryBuilder<D, CaseConvert, IsEnabled<EnablePage>, TRecord, AddPagingMeta<TResult, IsEnabled<EnablePage>>> | ||
& QueryBuilderExtMethod<D, CaseConvert, EnablePage, TRecord> | ||
& QueryBuilder<D, CaseConvert, EnablePage, TRecord, AddPagingMeta<TResult, EnablePage>> | ||
@@ -35,3 +42,3 @@ type OmitQueryBuilderKeys = 'select' | 'where' | 'orderBy' | keyof Knex.ChainableInterface | ||
CaseConvert extends CaseType = CaseType, | ||
EnablePage extends boolean = false, | ||
EnablePage extends PagingCategory = 0, | ||
TRecord extends {} = any, | ||
@@ -61,3 +68,3 @@ TResult = any | ||
export type TbQueryBuilder<D extends {}, CaseConvert extends CaseType, TRecord extends {}, Context> | ||
= (ctx?: Context) => KmoreQueryBuilder<D, CaseConvert, false, TRecord, TRecord[]> | ||
= (ctx?: Context) => KmoreQueryBuilder<D, CaseConvert, 0, TRecord, TRecord[]> | ||
@@ -75,3 +82,3 @@ interface QueryBuilderExtName<D extends {} = {}> { | ||
CaseConvert extends CaseType = CaseType, | ||
EnablePage extends boolean = false, | ||
EnablePage extends PagingCategory = 0, | ||
TRecord extends {} = any, | ||
@@ -90,9 +97,27 @@ > { | ||
CaseConvert extends CaseType = CaseType, | ||
TRecord extends {} = any | ||
> = (options?: Partial<PagingOptions>) => KmoreQueryBuilder<D, CaseConvert, true, TRecord, TRecord[]> | ||
TRecord extends {} = any, | ||
> = <Wrap extends boolean | undefined = false>(options?: Partial<PagingOptions>, wrapOutput?: Wrap) | ||
=> KmoreQueryBuilder<D, CaseConvert, CalcPagingCat<Wrap>, TRecord, TRecord[]> | ||
type CalcPagingCat<T> = T extends true ? 2 : 1 | ||
type AddPagingMeta< | ||
TSelection, | ||
EnablePage extends PagingCategory = 0 | ||
> = EnablePage extends 0 | ||
? TSelection | ||
: TSelection extends (infer R)[] | ||
? EnablePage extends 2 | ||
? WrapPageOutput<R> | ||
: PageRawType<R> | ||
: TSelection | ||
// type RemovePagingMeta<T> = T extends ((infer M)[] & PagingMeta) ? M[] : T | ||
type WrapPageOutput<T> = T extends PageWrapType ? T : PageWrapType<T> | ||
type SmartJoin< | ||
D extends {} = {}, | ||
CaseConvert extends CaseType = CaseType, | ||
EnablePage extends boolean = false, | ||
EnablePage extends PagingCategory = 0, | ||
TResult = unknown[] | ||
@@ -137,10 +162,9 @@ > = < | ||
} | ||
/** | ||
* Note: keyof PagingMeta is not enumerable | ||
*/ | ||
export type PageArrayType<T = unknown> = T[] & PagingMeta | ||
/** | ||
* Note: keyof PagingMeta is not enumerable | ||
*/ | ||
export type PageDataType<T = {}> = T & PagingMeta | ||
export type PageRawType<T = unknown> = T[] & PagingMeta | ||
export interface PageWrapType<T = unknown> extends PagingMeta { rows: T[] } | ||
export interface PagingMeta { | ||
@@ -154,7 +178,7 @@ /** | ||
*/ | ||
pageCountAll: number | ||
total: number | ||
/** | ||
* Current page number, start from 1 | ||
*/ | ||
pageCurrent: number | ||
page: number | ||
/** | ||
@@ -167,11 +191,3 @@ * Number of rows of each page. | ||
type AddPagingMeta<TSelection, EnablePage extends boolean = false> = EnablePage extends false | ||
? RemovePagingMeta<TSelection> | ||
: TSelection extends unknown[] | ||
? PageDataType<RemovePagingMeta<TSelection>> | ||
: TSelection | ||
type RemovePagingMeta<T> = T extends ((infer M)[] & PagingMeta) ? M[] : T | ||
/* ---------------- re-declare types of Knex ---------------- */ | ||
@@ -182,3 +198,3 @@ | ||
CaseConvert extends CaseType = CaseType, | ||
EnablePage extends boolean = false, | ||
EnablePage extends PagingCategory = 0, | ||
TRecord extends {} = any, TResult = unknown[] | ||
@@ -212,3 +228,3 @@ > extends | ||
CaseConvert extends CaseType = CaseType, | ||
EnablePage extends boolean = false, | ||
EnablePage extends PagingCategory = 0, | ||
TRecord extends {} = any, | ||
@@ -275,3 +291,3 @@ TResult = unknown[] | ||
CaseConvert extends CaseType = CaseType, | ||
EnablePage extends boolean = false, | ||
EnablePage extends PagingCategory = 0, | ||
TRecord extends {} = any, | ||
@@ -340,3 +356,3 @@ TResult = unknown[] | ||
CaseConvert extends CaseType = CaseType, | ||
EnablePage extends boolean = false, | ||
EnablePage extends PagingCategory = 0, | ||
TRecord extends {} = any, | ||
@@ -389,3 +405,2 @@ TResult = unknown[] | ||
type IncompatibleToAlt<T, TBase, TAlt> = T extends TBase ? T : TAlt | ||
type IsEnabled<T extends boolean> = T extends true ? true : false | ||
// Retain the association of original keys with aliased keys at type level | ||
@@ -655,3 +670,3 @@ // to facilitates type-safe aliasing for object syntax | ||
// this will combine all of them | ||
type ResolveResult<S, EnablePage extends boolean = false> | ||
type ResolveResult<S, EnablePage extends PagingCategory = 0> | ||
= AddPagingMeta<DeferredKeySelectionNS.Resolve<S>, EnablePage> | ||
@@ -664,3 +679,3 @@ | ||
CaseConvert extends CaseType = CaseType, | ||
EnablePage extends boolean = false, | ||
EnablePage extends PagingCategory = 0, | ||
TRecord extends {} = any, | ||
@@ -722,3 +737,3 @@ TResult = any | ||
CaseConvert extends CaseType = CaseType, | ||
EnablePage extends boolean = false, | ||
EnablePage extends PagingCategory = 0, | ||
TRecord extends {} = any, | ||
@@ -725,0 +740,0 @@ TResult = unknown[] |
import assert from 'assert' | ||
import { KmoreQueryBuilder, PagingMeta, PagingOptions } from './builder.types.js' | ||
import { KmoreQueryBuilder, PageWrapType, PagingMeta, PagingOptions } from './builder.types.js' | ||
import { defaultPropDescriptor } from './config.js' | ||
@@ -8,14 +8,26 @@ import { KmorePageKey } from './types.js' | ||
export const initPagingOptions: PagingOptions = { | ||
export const initPagingOptions: _PagingOptions = { | ||
enable: true, | ||
page: 1, | ||
pageSize: 10, | ||
wrapOutput: false, | ||
} | ||
export const initPagingMeta: PagingMeta = { | ||
pageCountAll: 0, | ||
pageCurrent: 1, | ||
total: 0, | ||
page: 1, | ||
pageSize: initPagingOptions.pageSize, | ||
} | ||
export const initPageTypeMaping: Record<keyof PageWrapType, string> = { | ||
total: 'total', | ||
page: 'page', | ||
pageSize: 'pageSize', | ||
rows: 'rows', | ||
} | ||
export interface _PagingOptions extends PagingOptions { | ||
wrapOutput: boolean | ||
} | ||
export function extRefTableFnPropertyAutoPaging(refTable: KmoreQueryBuilder): KmoreQueryBuilder { | ||
@@ -30,3 +42,6 @@ assert( | ||
writable: true, | ||
value: (options: Partial<PagingOptions>) => autoPagingBuilder(options, refTable), | ||
value: ( | ||
options?: Partial<PagingOptions>, | ||
wrapOutput?: boolean, | ||
) => autoPagingBuilder(options, wrapOutput ?? false, refTable), | ||
}) | ||
@@ -38,3 +53,4 @@ | ||
function autoPagingBuilder( | ||
options: Partial<PagingOptions>, | ||
options: Partial<PagingOptions> | undefined, | ||
wrapOutput: boolean, | ||
queryBuilder: KmoreQueryBuilder, | ||
@@ -47,6 +63,9 @@ ): KmoreQueryBuilder { | ||
const opts: PagingOptions = { | ||
const opts: _PagingOptions = { | ||
...initPagingOptions, | ||
...options, | ||
} | ||
if (wrapOutput === true) { | ||
opts.wrapOutput = true | ||
} | ||
assert(opts.page > 0, 'AutoPagingOptions page should be greater than 0') | ||
@@ -53,0 +72,0 @@ assert(opts.pageSize > 0, 'AutoPagingOptions pageSize should be greater than 0') |
@@ -36,2 +36,3 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
) { | ||
// pager() | ||
getThenProxyRet = resultPagerHandler({ builder: target, kmore }, createQueryBuilderGetProxy) | ||
@@ -38,0 +39,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
362447
5997
355