diff --git a/README.md b/README.md index aeb196e..3dfa406 100644 --- a/README.md +++ b/README.md @@ -423,7 +423,7 @@ With the some function you can order requested data. You can either merely order * ?orderBy=createdDate asc */ wServices['article'].some({ - orderBy: [{ FIELD: 'createdDate', SORT: 'asc' }] + orderBy: [{ FIELD: { createdDate: true }, SORT: 'asc' }] }); ``` @@ -435,7 +435,7 @@ wServices['article'].some({ * ?orderBy=createdDate asc, articleNumber desc */ wServices['article'].some({ - orderBy: [{ FIELD: 'createdDate' }, { FIELD: 'articleNumber', SORT: 'desc' }] + orderBy: [{ FIELD: { createdDate: true } }, { FIELD: { articleNumber: true }, SORT: 'desc' }] }); ``` @@ -457,7 +457,7 @@ wServices['article'].some({ ELSE: 3, SORT: 'asc' }, - { FIELD: 'articleNumber' } + { FIELD: { articleNumber: true } } ] }); ``` @@ -474,8 +474,8 @@ The `THEN` and `ELSE` values can also be a `FieldOrderBy` to fall back to a fiel wServices['article'].some({ orderBy: [ { - CASE: [{ WHEN: { internalNote: { NULL: false } }, THEN: { FIELD: 'articleNumber' } }], - ELSE: { FIELD: 'createdDate' }, + CASE: [{ WHEN: { internalNote: { NULL: false } }, THEN: { FIELD: { articleNumber: true } } }], + ELSE: { FIELD: { createdDate: true } }, SORT: 'asc' } ] @@ -491,7 +491,7 @@ For properties that are objects or arrays of objects, use dot-notation to refere * ?orderBy=articlePrices.price asc */ wServices['article'].some({ - orderBy: [{ FIELD: 'articlePrices.price', SORT: 'asc' }] + orderBy: [{ FIELD: { articlePrices: { price: true } }, SORT: 'asc' }] }); ``` @@ -511,7 +511,7 @@ wServices['party'].some({ TRIM: true, SORT: 'desc' }, - { FIELD: 'firstName' } + { FIELD: { firstName: true } } ] }); ``` diff --git a/src/generator/01-base/static/queriesWithQueryLanguage.ts.txt b/src/generator/01-base/static/queriesWithQueryLanguage.ts.txt index fb90dc8..ed7bfc2 100644 --- a/src/generator/01-base/static/queriesWithQueryLanguage.ts.txt +++ b/src/generator/01-base/static/queriesWithQueryLanguage.ts.txt @@ -19,11 +19,17 @@ const flattenOrderBy = (orderBy: OrderBy[] = []): string[] => { ): orderByItem is ConditionalOrderBy => !!orderByItem && typeof orderByItem === 'object' && 'CASE' in orderByItem; + /** Converts a OrderableField object to a dot-notation string. OrderableField guarantees exactly one key per level. */ + const flattenField = (field: OrderableField): string => { + const [[key, value]] = Object.entries(field); + return typeof value === 'object' && value !== null ? `${key}.${flattenField(value as OrderableField)}` : key; + }; + const flattenValue = (value: number | FieldOrderBy): string => { if (typeof value === 'number') { return value.toString(); } - return applyModifiers(value.FIELD, value); + return applyModifiers(flattenField(value.FIELD), value); }; const flattenConditional = (item: ConditionalOrderBy): string => { @@ -43,7 +49,7 @@ const flattenOrderBy = (orderBy: OrderBy[] = []): string[] => { } const field = orderByItem as FieldOrderBy; - const property = applyModifiers(field.FIELD, field); + const property = applyModifiers(flattenField(field.FIELD), field); const sort = field.SORT === 'desc' ? 'desc' : 'asc'; return `${property} ${sort}`; }; @@ -126,36 +132,32 @@ export type QueryFilter = SingleFilterExpr & { }; }; -export type ConditionalOrderByCase = { - WHEN: QueryFilter; - THEN: number | FieldOrderBy; +export type ConditionalOrderByCase = { + WHEN: QueryFilter; + THEN: number | FieldOrderBy; }; -export type ConditionalOrderBy = { - CASE: ConditionalOrderByCase[]; - ELSE: number | FieldOrderBy; +export type ConditionalOrderBy = { + CASE: ConditionalOrderByCase[]; + ELSE: number | FieldOrderBy; SORT?: 'asc' | 'desc'; }; -export type FieldPath = { - [K in keyof T & string]: NonNullable extends Array - ? U extends Record - ? `${K}.${FieldPath}` - : never - : NonNullable extends Record - ? K | `${K}.${FieldPath>}` - : K; -}[keyof T & string]; - -export type FieldOrderBy = { - FIELD: FieldPath; +export type OrderableField = { + [K in keyof F]-?: NonNullable extends Record + ? { [P in K]: OrderableField> } & { [P in Exclude]?: never } + : { [P in K]: boolean } & { [P in Exclude]?: never }; +}[keyof F]; + +export type FieldOrderBy = { + FIELD: OrderableField; SORT?: 'asc' | 'desc'; LOWER?: boolean; TRIM?: boolean; LENGTH?: boolean; }; -export type OrderBy = FieldOrderBy | ConditionalOrderBy; +export type OrderBy = FieldOrderBy | ConditionalOrderBy; export type CountQuery = { where?: QueryFilter; @@ -171,7 +173,7 @@ type SomeQueryBase = { }; export type SomeQuery = SomeQueryBase & - ({ sort?: Sort[]; orderBy?: never } | { sort?: never; orderBy?: OrderBy[] }); + ({ sort?: Sort[]; orderBy?: never } | { sort?: never; orderBy?: OrderBy[] }); const comparisonOperatorList: ComparisonOperator[] = [ 'EQ',