@weclapp/sdk 2.0.0-dev.57 → 2.0.0-dev.59

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 (2) hide show
  1. package/dist/cli.js +17 -4
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -138,7 +138,7 @@ var multiRequest = "type RequestTask = {\n uri: string;\n resolve: (result: un
138
138
 
139
139
  var queriesWithFilter = "export type EqualityOperator = 'EQ' | 'NE';\n\nexport type ComparisonOperator =\n | 'LT'\n | 'GT'\n | 'LE'\n | 'GE'\n | 'LIKE'\n | 'ILIKE'\n | 'NOT_LIKE'\n | 'NOT_ILIKE'\n | 'IEQ'\n | 'NOT_IEQ';\n\nexport type ArrayOperator = 'IN' | 'NOT_IN';\n\nexport type Operator = EqualityOperator | ComparisonOperator | ArrayOperator;\n\nexport type MapOperators<T> = { [K in EqualityOperator]?: T | null } & { [K in ComparisonOperator]?: T } & {\n [K in ArrayOperator]?: T[];\n};\n\nexport type QueryFilter<T> = {\n [P in keyof T]?: T[P] extends Array<infer U> | undefined\n ? U extends Record<any, any>\n ? QueryFilter<U>\n : MapOperators<U>\n : T[P] extends Record<any, any> | undefined\n ? QueryFilter<T[P]>\n : MapOperators<T[P]>;\n};\n\nexport type CountQuery<F> = {\n filter?: QueryFilter<F>;\n or?: (QueryFilter<F> & CustomAttributeFilter)[];\n};\n\nexport type SomeQuery<E, F, I, P> = {\n serializeNulls?: boolean;\n include?: QuerySelect<I>;\n properties?: P;\n filter?: QueryFilter<F> & CustomAttributeFilter;\n select?: QuerySelect<E>;\n or?: (QueryFilter<F> & CustomAttributeFilter)[];\n sort?: Sort<E>[];\n pagination?: Pagination;\n};\n\nconst equality: string[] = ['EQ', 'NE', 'IEQ', 'NOT_IEQ'];\n\nconst simple: string[] = [...equality, 'LT', 'GT', 'LE', 'GE', 'LIKE', 'NOT_LIKE', 'ILIKE', 'NOT_ILIKE'];\n\nconst array: string[] = ['IN', 'NOT_IN'];\n\nconst filterMap: Record<Operator, string> = {\n EQ: 'eq',\n NE: 'ne',\n LT: 'lt',\n GT: 'gt',\n LE: 'le',\n GE: 'ge',\n LIKE: 'like',\n NOT_LIKE: 'notlike',\n ILIKE: 'ilike',\n NOT_ILIKE: 'notilike',\n IN: 'in',\n NOT_IN: 'notin',\n IEQ: 'ieq',\n NOT_IEQ: 'notieq'\n};\n\nconst flattenCustomAttributes = (obj: CustomAttributeFilter = {}): [string, string][] => {\n const entries: [string, string][] = [];\n\n for (const [id, filter] of Object.entries(obj)) {\n const key = `customAttribute${id}`;\n\n if (typeof filter === 'object') {\n for (const [prop, value] of Object.entries(filter)) {\n entries.push([`${key}.${prop}-eq`, String(value)]);\n }\n } else if (filter !== undefined) {\n entries.push([`${key}-eq`, String(filter)]);\n }\n }\n\n return entries;\n};\n\nconst flatten = (obj: QueryFilter<any> = {}): [string, string][] => {\n const entries: [string, string][] = [];\n\n for (const [prop, propValue] of Object.entries(obj)) {\n for (const [filter, value] of Object.entries(propValue as object)) {\n if (value === undefined) continue;\n\n if (simple.includes(filter) || array.includes(filter)) {\n if (value === null && equality.includes(filter)) {\n entries.push([`${prop}-${filter === 'EQ' ? 'null' : 'notnull'}`, '']);\n } else {\n entries.push([`${prop}-${filterMap[filter as Operator]}`, value]);\n }\n } else {\n entries.push(\n ...(flatten(propValue as QueryFilter<any>).map((v) => [`${prop}.${v[0]}`, v[1]]) as [string, string][])\n );\n break;\n }\n }\n }\n\n return entries;\n};\n\nconst flattenFilter = (obj: QueryFilter<any> = {}): Record<string, string> => {\n const filter: [string, any][] = [],\n customAttributes: [string, any][] = [];\n\n Object.entries(obj).forEach((value) => {\n (value[0].match(/^\\d+$/) ? customAttributes : filter).push(value);\n });\n\n return Object.fromEntries([\n ...flatten(Object.fromEntries(filter)),\n ...flattenCustomAttributes(Object.fromEntries(customAttributes) as CustomAttributeFilter)\n ]);\n};\n\nconst flattenOrFilter = (obj: QueryFilter<any>[] = []): Record<string, string> => {\n const entries: [string, any][] = [];\n\n for (let i = 0; i < obj.length; i++) {\n entries.push(...(flatten(obj[i]).map((v) => [`or${i || ''}-${v[0]}`, v[1]]) as [string, string][]));\n }\n\n return Object.fromEntries(entries);\n};\n\nconst _count = (\n cfg: ServiceConfig | undefined,\n endpoint: string,\n query?: CountQuery<any> & { params?: Record<any, any> },\n requestOptions?: RequestOptions\n) =>\n{\n const usePost = cfg?.usePost ?? globalConfig?.usePost\n const payload = {\n ...flattenFilter(query?.filter),\n ...flattenOrFilter(query?.or),\n ...query?.params\n }\n\n return wrapResponse(() =>\n raw(cfg, endpoint, {\n method: usePost ? 'POST' : 'GET',\n unwrap: true,\n ...(usePost ? { body: payload } : { query: payload })\n }, requestOptions)\n )\n };\n\nconst _some = (\n cfg: ServiceConfig | undefined,\n endpoint: string,\n query?: SomeQuery<any, any, any, any> & { params?: Record<any, any> },\n requestOptions?: RequestOptions\n) =>\n{\n const usePost = cfg?.usePost ?? globalConfig?.usePost\n const payload = {\n serializeNulls: query?.serializeNulls,\n additionalProperties: query?.properties?.join(','),\n properties: query?.select ? flattenSelect(query.select).join(',') : undefined,\n includeReferencedEntities: query?.include ? Object.keys(query.include).join(',') : undefined,\n ...flattenOrFilter(query?.or),\n ...flattenFilter(query?.filter),\n ...flattenSort(query?.sort),\n ...query?.params,\n ...query?.pagination\n }\n\n return wrapResponse(() =>\n raw(cfg, usePost ? `${endpoint}/query` : endpoint, {\n method: usePost ? 'POST' : 'GET',\n ...(usePost ? { body: payload } : { query: payload })\n }, requestOptions).then((data) => ({\n entities: data.result,\n references: data.referencedEntities ?? {},\n properties: data.additionalProperties ?? {}\n }))\n )\n };\n";
140
140
 
141
- var queriesWithQueryLanguage = "const flattenOrderBy = (orderBy: OrderBy<any>[] = []): string => {\n\n const applyModifiers = (property: string, modifier: { TRIM?: boolean; LOWER?: boolean; LENGTH?: boolean }) => {\n let result = property;\n if (modifier.TRIM) {\n result = `trim(${result})`;\n }\n if (modifier.LOWER) {\n result = `lower(${result})`;\n }\n if (modifier.LENGTH) {\n result = `length(${result})`;\n }\n return result;\n };\n\n const isConditionalOrderBy = (\n orderByItem: OrderBy<any>\n ): orderByItem is ConditionalOrderBy<any> =>\n !!orderByItem && typeof orderByItem === 'object' && 'CASE' in orderByItem;\n\n const flattenValue = (value: number | FieldOrderBy<any>): string => {\n if (typeof value === 'number') {\n return value.toString();\n }\n return applyModifiers(value.FIELD, value);\n };\n\n const flattenConditional = (item: ConditionalOrderBy<any>): string => {\n const cases = item.CASE.map((c) => {\n const whenStr = flattenWhere(c.WHEN as QueryFilter<any>, []).join(' and ');\n return `(${whenStr}) ? ${flattenValue(c.THEN)}`;\n });\n\n return cases.reduceRight((acc, caseStr) => `${caseStr} : ${acc}`, flattenValue(item.ELSE));\n };\n\n const flattenSingle = (orderByItem: OrderBy<any>): string => {\n if (isConditionalOrderBy(orderByItem)) {\n const expr = flattenConditional(orderByItem);\n const sort = orderByItem.SORT === 'desc' ? 'desc' : 'asc';\n return `${expr} ${sort}`;\n }\n\n const field = orderByItem as FieldOrderBy<any>;\n const property = applyModifiers(field.FIELD, field);\n const sort = field.SORT === 'desc' ? 'desc' : 'asc';\n return `${property} ${sort}`;\n };\n\n return orderBy.map(flattenSingle).join(', ');\n}\n\nexport type ComparisonOperator =\n | 'EQ'\n | 'NE'\n | 'LT'\n | 'GT'\n | 'LE'\n | 'GE'\n | 'LIKE';\n\nexport type LengthOperator = 'LENGTH';\n\nexport type ArrayOperator = 'IN';\n\nexport type NullOperator = 'NULL';\n\nexport type Operator = ComparisonOperator | ArrayOperator | NullOperator;\n\nexport type ModifierFunction = 'LOWER' | 'TRIM';\n\n// use globalThis to use typescript's 'Pick', since the SDK contains an interface which is also called 'Pick'\nexport type RequireAtLeastOne<T> = {\n [K in keyof T]-?: Required<globalThis.Pick<T, K>> & Partial<Omit<T, K>>;\n}[keyof T];\n\nexport type LengthExpr = {\n [K in LengthOperator]: {\n [K in Exclude<ComparisonOperator, 'LIKE'>]?: number\n }\n};\n\nexport type LengthExprWithModifier =\n LengthExpr &\n { [K in ComparisonOperator]?: never } &\n { [K in ArrayOperator]?: never } &\n { [K in NullOperator]?: never } &\n { [K in ModifierFunction]?: boolean };\n\nexport type FilterExpr<T> =\n { [K in ComparisonOperator]?: T } &\n { [K in ArrayOperator]?: T[] } &\n { [K in keyof LengthExpr]?: never };\n\nexport type FilterExprWithoutNull<T> =\n RequireAtLeastOne<FilterExpr<T>> &\n { [K in NullOperator]?: never } &\n { [K in ModifierFunction]?: boolean };\n\nexport type FilterExprWithNull<T> =\n FilterExpr<T> &\n { [K in NullOperator]?: boolean} &\n { [K in ModifierFunction]?: never };\n\nexport type MapOperators<T> = LengthExprWithModifier | FilterExprWithoutNull<T> | FilterExprWithNull<T>;\n\nexport type SingleFilterExpr<T> = {\n [P in keyof T]?: T[P] extends Array<infer U> | undefined\n ? U extends Record<any, any>\n ? SingleFilterExpr<U> | { NOT?: SingleFilterExpr<U> }\n : MapOperators<U>\n : T[P] extends Record<any, any> | undefined\n ? SingleFilterExpr<T[P]> | { NOT?: SingleFilterExpr<T[P]> }\n : MapOperators<T[P]>;\n};\n\nexport type QueryFilter<T> = SingleFilterExpr<T> & {\n OR?: QueryFilter<T>[];\n AND?: QueryFilter<T>[];\n NOT?: QueryFilter<T>;\n};\n\nexport type ConditionalOrderByCase<E> = {\n WHEN: QueryFilter<E>;\n THEN: number | FieldOrderBy<E>;\n};\n\nexport type ConditionalOrderBy<E> = {\n CASE: ConditionalOrderByCase<E>[];\n ELSE: number | FieldOrderBy<E>;\n SORT?: 'asc' | 'desc';\n};\n\nexport type FieldPath<T> = {\n [K in keyof T & string]: NonNullable<T[K]> extends Array<infer U>\n ? U extends Record<any, any>\n ? `${K}.${FieldPath<U>}`\n : never\n : NonNullable<T[K]> extends Record<any, any>\n ? K | `${K}.${FieldPath<NonNullable<T[K]>>}`\n : K;\n}[keyof T & string];\n\nexport type FieldOrderBy<E> = {\n FIELD: FieldPath<E>;\n SORT?: 'asc' | 'desc';\n LOWER?: boolean;\n TRIM?: boolean;\n LENGTH?: boolean;\n};\n\nexport type OrderBy<E> = FieldOrderBy<E> | ConditionalOrderBy<E>;\n\nexport type CountQuery<F> = {\n where?: QueryFilter<F>;\n};\n\ntype SomeQueryBase<E, F, I, P> = {\n serializeNulls?: boolean;\n include?: QuerySelect<I>;\n properties?: P;\n where?: QueryFilter<F>;\n select?: QuerySelect<E>;\n pagination?: Pagination;\n};\n\nexport type SomeQuery<E, F, I, P> = SomeQueryBase<E, F, I, P> &\n ({ sort?: Sort<E>[]; orderBy?: never } | { sort?: never; orderBy?: OrderBy<E>[] });\n\nconst comparisonOperatorList: ComparisonOperator[] = [\n 'EQ',\n 'NE',\n 'LT',\n 'GT',\n 'LE',\n 'GE',\n 'LIKE'\n];\n\nconst comparisonOperatorMap: Record<Operator, string> = {\n EQ: '=',\n NE: '!=',\n LT: '<',\n GT: '>',\n LE: '<=',\n GE: '>=',\n LIKE: '~',\n IN: 'in',\n NULL: 'null'\n};\n\nconst modifierFunctionList: ModifierFunction[] = ['LOWER', 'TRIM'];\n\nconst flattenWhere = (\n obj: QueryFilter<any> = {},\n nestedPaths: string[]\n): string[] => {\n const entries: string[] = [];\n for (const [prop, propValue] of Object.entries(obj)) {\n const setModifiers = findAllModifierFunctions(propValue ?? {}, modifierFunctionList).filter(\n (modifier) => modifier[1]\n );\n if (prop === 'OR') {\n const flattedOr: string[][] = [];\n for (let i = 0; i < (obj.OR?.length ?? 0); i++) {\n flattedOr.push(flattenWhere(obj.OR?.[i], nestedPaths));\n }\n entries.push(\n `(${flattedOr\n .map((x) => {\n const joined = x.join(' and ');\n\n if (x.length > 1) {\n return `(${joined})`;\n } else {\n return joined;\n }\n })\n .join(' or ')})`\n );\n } else if (prop === 'AND') {\n const flattedAnd: string[][] = [];\n for (let i = 0; i < (obj.AND?.length ?? 0); i++) {\n flattedAnd.push(flattenWhere(obj.AND?.[i], nestedPaths));\n }\n entries.push(\n `(${flattedAnd\n .map((x) => {\n const joined = x.join(' and ');\n\n if (x.length > 1) {\n return `(${joined})`;\n } else {\n return joined;\n }\n })\n .join(' and ')})`\n );\n } else if (prop === 'NOT') {\n const flattedNot = flattenWhere(obj.NOT, nestedPaths);\n entries.push(\n `not ${flattedNot.length > 1 ? '(' : ''}${flattedNot.join(' and ')}${flattedNot.length > 1 ? ')' : ''}`\n );\n } else if (propValue) {\n for (const [operator, value] of Object.entries(propValue)) {\n if (value === undefined) continue;\n if (comparisonOperatorList.includes(operator as ComparisonOperator)) {\n entries.push(\n `${setModifiers.reduce(\n (acc, [first]) => `${first.toLowerCase()}(${acc})`,\n nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')\n )} ${comparisonOperatorMap[operator as Operator]} ${\n typeof value === 'string' ? JSON.stringify(value) : value\n }`\n );\n } else if ((operator as Operator) === 'NULL') {\n entries.push(\n `${!value ? 'not ' : ''}${nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')} ${comparisonOperatorMap[operator as Operator]}`\n );\n } else if ((operator as Operator) === 'IN') {\n if(value.length === 0) {\n entries.push('1 = 0')\n } else {\n entries.push(\n `${setModifiers.reduce(\n (acc, [first]) => `${first.toLowerCase()}(${acc})`,\n nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')\n )} ${comparisonOperatorMap[operator as Operator]} [${value.map((v: string | number) =>\n typeof v === 'string' ? JSON.stringify(v) : v\n )}]`\n );\n }\n } else if ((operator as LengthOperator) === 'LENGTH') {\n const lengthProp = `length(${setModifiers.reduce(\n (acc, [first]) => `${first.toLowerCase()}(${acc})`,\n nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')\n )})`;\n entries.push(...flattenWhere({ [lengthProp]: value } as QueryFilter<any>, []));\n } else if (\n !modifierFunctionList.includes(operator as ModifierFunction)\n && typeof value === 'object'\n ) {\n entries.push(\n ...flattenWhere(propValue as QueryFilter<any>, [\n ...nestedPaths,\n prop\n ])\n );\n break;\n }\n }\n }\n }\n return entries;\n};\n\nconst assembleOrderBy = (orderBy: OrderBy<any>[] = []): Record<string, string> => {\n if(!orderBy.length) {\n return {}\n }\n const flattedOrderBy = flattenOrderBy(orderBy);\n return flattedOrderBy.length ? { orderBy: flattedOrderBy } : {};\n}\n\nconst assembleFilterParam = (\n obj: QueryFilter<any> = {}\n): Record<string, string> => {\n const flattedFilter = flattenWhere(obj, []);\n return flattedFilter.length ? { filter: flattedFilter.join(' and ') } : {};\n};\n\nconst findAllModifierFunctions = (\n obj: Record<string, any>,\n types: ModifierFunction[]\n) => {\n const result: [string, any][] = [];\n for (const key in obj) {\n if (types.includes(key as ModifierFunction)) {\n result[types.indexOf(key as ModifierFunction)] = [key, obj[key]];\n }\n }\n return result.filter((modifierTuple) => modifierTuple);\n};\n\nconst _count = (\n cfg: ServiceConfig | undefined,\n endpoint: string,\n query?: CountQuery<any> & { params?: Record<any, any> },\n requestOptions?: RequestOptions\n) =>\n {\n const usePost = cfg?.usePost ?? globalConfig?.usePost\n const payload = {\n ...assembleFilterParam(query?.where),\n ...query?.params\n }\n\n return wrapResponse(() =>\n raw(cfg, endpoint, {\n unwrap: true,\n method: usePost ? 'POST' : 'GET',\n ...(usePost ? { body: payload } : { query: payload })\n }, requestOptions)\n )\n };\n\nconst _some = (\n cfg: ServiceConfig | undefined,\n endpoint: string,\n query?: SomeQuery<any, any, any, any> & { params?: Record<any, any> },\n requestOptions?: RequestOptions\n) => {\n const usePost = cfg?.usePost ?? globalConfig?.usePost;\n const payload = {\n serializeNulls: query?.serializeNulls,\n additionalProperties: query?.properties?.join(','),\n properties: query?.select\n ? flattenSelect(query.select).join(',')\n : undefined,\n includeReferencedEntities: query?.include\n ? Object.keys(query.include).join(',')\n : undefined,\n ...assembleFilterParam(query?.where),\n ...flattenSort(query?.sort),\n ...assembleOrderBy(query?.orderBy),\n ...query?.params,\n ...query?.pagination\n };\n return wrapResponse(() =>\n raw(cfg, usePost ? `${endpoint}/query` : endpoint, {\n method: usePost ? 'POST' : 'GET',\n ...(usePost ? { body: payload } : { query: payload })\n }, requestOptions).then((data) => ({\n entities: data.result,\n references: data.referencedEntities ?? {},\n properties: data.additionalProperties ?? {}\n }))\n );\n};\n";
141
+ var queriesWithQueryLanguage = "const flattenOrderBy = (orderBy: OrderBy<any>[] = []): string => {\n\n const applyModifiers = (property: string, modifier: { TRIM?: boolean; LOWER?: boolean; LENGTH?: boolean }) => {\n let result = property;\n if (modifier.TRIM) {\n result = `trim(${result})`;\n }\n if (modifier.LOWER) {\n result = `lower(${result})`;\n }\n if (modifier.LENGTH) {\n result = `length(${result})`;\n }\n return result;\n };\n\n const isConditionalOrderBy = (\n orderByItem: OrderBy<any>\n ): orderByItem is ConditionalOrderBy<any> =>\n !!orderByItem && typeof orderByItem === 'object' && 'CASE' in orderByItem;\n\n const flattenValue = (value: number | FieldOrderBy<any>): string => {\n if (typeof value === 'number') {\n return value.toString();\n }\n return applyModifiers(value.FIELD, value);\n };\n\n const flattenConditional = (item: ConditionalOrderBy<any>): string => {\n const cases = item.CASE.map((c) => {\n const whenStr = flattenWhere(c.WHEN as QueryFilter<any>, []).join(' and ');\n return `(${whenStr}) ? ${flattenValue(c.THEN)}`;\n });\n\n return cases.reduceRight((acc, caseStr) => `${caseStr} : ${acc}`, flattenValue(item.ELSE));\n };\n\n const flattenSingle = (orderByItem: OrderBy<any>): string => {\n if (isConditionalOrderBy(orderByItem)) {\n const expr = flattenConditional(orderByItem);\n const sort = orderByItem.SORT === 'desc' ? 'desc' : 'asc';\n return `${expr} ${sort}`;\n }\n\n const field = orderByItem as FieldOrderBy<any>;\n const property = applyModifiers(field.FIELD, field);\n const sort = field.SORT === 'desc' ? 'desc' : 'asc';\n return `${property} ${sort}`;\n };\n\n return orderBy.map(flattenSingle).join(', ');\n}\n\nexport type ComparisonOperator =\n | 'EQ'\n | 'NE'\n | 'LT'\n | 'GT'\n | 'LE'\n | 'GE'\n | 'LIKE';\n\nexport type LengthOperator = 'LENGTH';\n\nexport type ArrayOperator = 'IN';\n\nexport type CaseOperator = 'CASE';\n\nexport type CaseNode<Entity, PropType> = {\n [K in CaseOperator]: CaseExpression<Entity, PropType>;\n};\n\ntype InCaseNode<Case> = Case extends CaseNode<infer Entity, infer PropType> ? CaseNode<Entity, PropType[]> : never;\n\nexport type CaseExpression<Entity, PropType> = {\n IF: SingleFilterExpr<Entity>;\n THEN: PropType | CaseNode<Entity, PropType>;\n ELSE: PropType | CaseNode<Entity, PropType>;\n};\n\nexport type NullOperator = 'NULL';\n\nexport type Operator = ComparisonOperator | ArrayOperator | CaseOperator | NullOperator;\n\nexport type BinaryOperator = Exclude<Operator, CaseOperator>;\n\nexport type ModifierFunction = 'LOWER' | 'TRIM';\n\n// use globalThis to use typescript's 'Pick', since the SDK contains an interface which is also called 'Pick'\nexport type RequireAtLeastOne<T> = {\n [K in keyof T]-?: Required<globalThis.Pick<T, K>> & Partial<Omit<T, K>>;\n}[keyof T];\n\nexport type LengthExpr = {\n [K in LengthOperator]: {\n [K in Exclude<ComparisonOperator, 'LIKE'>]?: number\n }\n};\n\nexport type LengthExprWithModifier =\n LengthExpr &\n { [K in ComparisonOperator]?: never } &\n { [K in ArrayOperator]?: never } &\n { [K in NullOperator]?: never } &\n { [K in ModifierFunction]?: boolean };\n\nexport type FilterExpr<T, Case = never> =\n { [K in ComparisonOperator]?: T | Case } &\n { [K in ArrayOperator]?: T[] | InCaseNode<Case> } &\n { [K in keyof LengthExpr]?: never };\n\nexport type FilterExprWithoutNull<T, Case = never> =\n RequireAtLeastOne<FilterExpr<T, Case>> &\n { [K in NullOperator]?: never } &\n { [K in ModifierFunction]?: boolean };\n\nexport type FilterExprWithNull<T, Case = never> =\n FilterExpr<T, Case> &\n { [K in NullOperator]?: boolean} &\n { [K in ModifierFunction]?: never };\n\nexport type MapOperators<T, Case = never> = LengthExprWithModifier | FilterExprWithoutNull<T, Case> | FilterExprWithNull<T, Case>;\n\nexport type SingleFilterExpr<T> = {\n [P in keyof T]?: T[P] extends Array<infer U> | undefined\n ? U extends Record<any, any>\n ? SingleFilterExpr<U> | { NOT?: SingleFilterExpr<U> }\n : MapOperators<U, CaseNode<T, T[P]>>\n : T[P] extends Record<any, any> | undefined\n ? SingleFilterExpr<T[P]> | { NOT?: SingleFilterExpr<T[P]> }\n : MapOperators<T[P], CaseNode<T, T[P]>>;\n};\n\nexport type QueryFilter<T> = SingleFilterExpr<T> & {\n OR?: QueryFilter<T>[];\n AND?: QueryFilter<T>[];\n NOT?: QueryFilter<T>;\n};\n\nexport type ConditionalOrderByCase<E> = {\n WHEN: QueryFilter<E>;\n THEN: number | FieldOrderBy<E>;\n};\n\nexport type ConditionalOrderBy<E> = {\n CASE: ConditionalOrderByCase<E>[];\n ELSE: number | FieldOrderBy<E>;\n SORT?: 'asc' | 'desc';\n};\n\nexport type FieldPath<T> = {\n [K in keyof T & string]: NonNullable<T[K]> extends Array<infer U>\n ? U extends Record<any, any>\n ? `${K}.${FieldPath<U>}`\n : never\n : NonNullable<T[K]> extends Record<any, any>\n ? K | `${K}.${FieldPath<NonNullable<T[K]>>}`\n : K;\n}[keyof T & string];\n\nexport type FieldOrderBy<E> = {\n FIELD: FieldPath<E>;\n SORT?: 'asc' | 'desc';\n LOWER?: boolean;\n TRIM?: boolean;\n LENGTH?: boolean;\n};\n\nexport type OrderBy<E> = FieldOrderBy<E> | ConditionalOrderBy<E>;\n\nexport type CountQuery<F> = {\n where?: QueryFilter<F>;\n};\n\ntype SomeQueryBase<E, F, I, P> = {\n serializeNulls?: boolean;\n include?: QuerySelect<I>;\n properties?: P;\n where?: QueryFilter<F>;\n select?: QuerySelect<E>;\n pagination?: Pagination;\n};\n\nexport type SomeQuery<E, F, I, P> = SomeQueryBase<E, F, I, P> &\n ({ sort?: Sort<E>[]; orderBy?: never } | { sort?: never; orderBy?: OrderBy<E>[] });\n\nconst comparisonOperatorList: ComparisonOperator[] = [\n 'EQ',\n 'NE',\n 'LT',\n 'GT',\n 'LE',\n 'GE',\n 'LIKE'\n];\n\nconst comparisonOperatorMap: Record<BinaryOperator, string> = {\n EQ: '=',\n NE: '!=',\n LT: '<',\n GT: '>',\n LE: '<=',\n GE: '>=',\n LIKE: '~',\n IN: 'in',\n NULL: 'null'\n};\n\nconst modifierFunctionList: ModifierFunction[] = ['LOWER', 'TRIM'];\n\nconst flattenWhere = (\n obj: QueryFilter<any> = {},\n nestedPaths: string[]\n): string[] => {\n const entries: string[] = [];\n for (const [prop, propValue] of Object.entries(obj)) {\n const setModifiers = findAllModifierFunctions(propValue ?? {}, modifierFunctionList).filter(\n (modifier) => modifier[1]\n );\n if (prop === 'OR') {\n const flattedOr: string[][] = [];\n for (let i = 0; i < (obj.OR?.length ?? 0); i++) {\n flattedOr.push(flattenWhere(obj.OR?.[i], nestedPaths));\n }\n entries.push(\n `(${flattedOr\n .map((x) => {\n const joined = x.join(' and ');\n\n if (x.length > 1) {\n return `(${joined})`;\n } else {\n return joined;\n }\n })\n .join(' or ')})`\n );\n } else if (prop === 'AND') {\n const flattedAnd: string[][] = [];\n for (let i = 0; i < (obj.AND?.length ?? 0); i++) {\n flattedAnd.push(flattenWhere(obj.AND?.[i], nestedPaths));\n }\n entries.push(\n `(${flattedAnd\n .map((x) => {\n const joined = x.join(' and ');\n\n if (x.length > 1) {\n return `(${joined})`;\n } else {\n return joined;\n }\n })\n .join(' and ')})`\n );\n } else if (prop === 'NOT') {\n const flattedNot = flattenWhere(obj.NOT, nestedPaths);\n entries.push(\n `not ${flattedNot.length > 1 ? '(' : ''}${flattedNot.join(' and ')}${flattedNot.length > 1 ? ')' : ''}`\n );\n } else if (prop === 'CASE') {\n entries.push(evaluateCaseExpression(propValue as CaseExpression<any, any>, setModifiers, nestedPaths));\n } else if (propValue) {\n for (const [operator, value] of Object.entries(propValue)) {\n if (value === undefined) continue;\n if (comparisonOperatorList.includes(operator as ComparisonOperator)) {\n entries.push(\n `${setModifiers.reduce(\n (acc, [first]) => `${first.toLowerCase()}(${acc})`,\n nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')\n )} ${comparisonOperatorMap[operator as BinaryOperator]} ${\n typeof value === 'object'\n ? flattenWhere(value, nestedPaths)\n : typeof value === 'string'\n ? setModifiers.reduce((acc, [first]) => `${first}(${acc})`, JSON.stringify(value))\n : value\n }`\n );\n } else if ((operator as Operator) === 'NULL') {\n entries.push(\n `${!value ? 'not ' : ''}${nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')} ${comparisonOperatorMap[operator as BinaryOperator]}`\n );\n } else if ((operator as Operator) === 'IN') {\n if (typeof value === 'object' && !Array.isArray(value) && value.CASE) {\n entries.push(\n `${setModifiers.reduce(\n (acc, [first]) => `${first}(${acc})`,\n nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')\n )} ${comparisonOperatorMap[operator as BinaryOperator]} ${evaluateCaseExpression(value.CASE as CaseExpression<any, any>, setModifiers, nestedPaths)}`\n );\n } else if(value.length === 0) {\n entries.push('1 = 0')\n } else {\n entries.push(\n `${setModifiers.reduce(\n (acc, [first]) => `${first.toLowerCase()}(${acc})`,\n nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')\n )} ${comparisonOperatorMap[operator as BinaryOperator]} [${value.map((v: string | number) =>\n typeof v === 'string' ? setModifiers.reduce((acc, [first]) => `${first}(${acc})`, JSON.stringify(v)) : v\n )}]`\n );\n }\n } else if ((operator as Operator) === 'CASE') {\n entries.push(evaluateCaseExpression(value as CaseExpression<any, any>, setModifiers, nestedPaths));\n } else if ((operator as LengthOperator) === 'LENGTH') {\n const lengthProp = `length(${setModifiers.reduce(\n (acc, [first]) => `${first.toLowerCase()}(${acc})`,\n nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')\n )})`;\n entries.push(...flattenWhere({ [lengthProp]: value } as QueryFilter<any>, []));\n } else if (\n !modifierFunctionList.includes(operator as ModifierFunction)\n && typeof value === 'object'\n ) {\n entries.push(\n ...flattenWhere(propValue as QueryFilter<any>, [\n ...nestedPaths,\n prop\n ])\n );\n break;\n }\n }\n }\n }\n return entries;\n};\n\nconst evaluateCaseExpression = <FilterProps, PropType>(\n exp: CaseExpression<FilterProps, PropType>,\n setModifiers: [string, any][],\n nestedPaths: string[]\n): string =>\n `(${flattenWhere(exp.IF, nestedPaths)} ? ${\n typeof exp.THEN === 'string' || Array.isArray(exp.THEN)\n ? setModifiers.reduce((acc, [first]) => `${first}(${acc})`, JSON.stringify(exp.THEN))\n : typeof exp.THEN === 'number' || typeof exp.THEN === 'boolean'\n ? exp.THEN\n : evaluateCaseExpression((exp.THEN as CaseNode<FilterProps, PropType>).CASE, setModifiers, nestedPaths)\n } : ${\n typeof exp.ELSE === 'string' || Array.isArray(exp.ELSE)\n ? setModifiers.reduce((acc, [first]) => `${first}(${acc})`, JSON.stringify(exp.ELSE))\n : typeof exp.ELSE === 'number' || typeof exp.ELSE === 'boolean'\n ? exp.ELSE\n : evaluateCaseExpression((exp.ELSE as CaseNode<FilterProps, PropType>).CASE, setModifiers, nestedPaths)\n })`;\n\nconst assembleOrderBy = (orderBy: OrderBy<any>[] = []): Record<string, string> => {\n if(!orderBy.length) {\n return {}\n }\n const flattedOrderBy = flattenOrderBy(orderBy);\n return flattedOrderBy.length ? { orderBy: flattedOrderBy } : {};\n}\n\nconst assembleFilterParam = (\n obj: QueryFilter<any> = {}\n): Record<string, string> => {\n const flattedFilter = flattenWhere(obj, []);\n return flattedFilter.length ? { filter: flattedFilter.join(' and ') } : {};\n};\n\nconst findAllModifierFunctions = (\n obj: Record<string, any>,\n types: ModifierFunction[]\n) => {\n const result: [string, any][] = [];\n for (const key in obj) {\n if (types.includes(key as ModifierFunction)) {\n result[types.indexOf(key as ModifierFunction)] = [key, obj[key]];\n }\n }\n return result.filter((modifierTuple) => modifierTuple);\n};\n\nconst _count = (\n cfg: ServiceConfig | undefined,\n endpoint: string,\n query?: CountQuery<any> & { params?: Record<any, any> },\n requestOptions?: RequestOptions\n) =>\n {\n const usePost = cfg?.usePost ?? globalConfig?.usePost\n const payload = {\n ...assembleFilterParam(query?.where),\n ...query?.params\n }\n\n return wrapResponse(() =>\n raw(cfg, endpoint, {\n unwrap: true,\n method: usePost ? 'POST' : 'GET',\n ...(usePost ? { body: payload } : { query: payload })\n }, requestOptions)\n )\n };\n\nconst _some = (\n cfg: ServiceConfig | undefined,\n endpoint: string,\n query?: SomeQuery<any, any, any, any> & { params?: Record<any, any> },\n requestOptions?: RequestOptions\n) => {\n const usePost = cfg?.usePost ?? globalConfig?.usePost;\n const payload = {\n serializeNulls: query?.serializeNulls,\n additionalProperties: query?.properties?.join(','),\n properties: query?.select\n ? flattenSelect(query.select).join(',')\n : undefined,\n includeReferencedEntities: query?.include\n ? Object.keys(query.include).join(',')\n : undefined,\n ...assembleFilterParam(query?.where),\n ...flattenSort(query?.sort),\n ...assembleOrderBy(query?.orderBy),\n ...query?.params,\n ...query?.pagination\n };\n return wrapResponse(() =>\n raw(cfg, usePost ? `${endpoint}/query` : endpoint, {\n method: usePost ? 'POST' : 'GET',\n ...(usePost ? { body: payload } : { query: payload })\n }, requestOptions).then((data) => ({\n entities: data.result,\n references: data.referencedEntities ?? {},\n properties: data.additionalProperties ?? {}\n }))\n );\n};\n";
142
142
 
143
143
  var root = "export const raw = async (\n cfg: ServiceConfig | undefined,\n endpoint: string,\n payload: RequestPayload = {},\n requestOptions?: RequestOptions\n): Promise<any> => {\n if (!cfg && !globalConfig) {\n throw new Error(`ServiceConfig missing.`);\n }\n\n const localCfg = {\n ...globalConfig,\n ...cfg,\n interceptors: { ...globalConfig?.interceptors, ...cfg?.interceptors }\n };\n\n const isBinaryData = payload.body instanceof resolveBinaryObject();\n const params = new URLSearchParams(Object.entries(payload.query ?? {}).filter((v) => v[1] !== undefined)\n .map(([key, value]) => [key, typeof value === 'string' ? value : JSON.stringify(value)])\n );\n\n const protocol = getProtocol(localCfg);\n\n const interceptRequest = localCfg.interceptors?.request ?? ((v) => v);\n const interceptResponse = localCfg.interceptors?.response ?? ((v) => v);\n\n const host = getHost(localCfg);\n\n let data;\n if (!cfg && localCfg.multiRequest) {\n let ep = endpoint;\n if (endpoint.startsWith('/')) {\n ep = endpoint.replace('/', '');\n }\n data = await addRequest(`${ep}?${params}`);\n } else {\n const request = new Request(`${protocol}//${host}/webapp/api/v${apiVersion}${endpoint}?${params}`, {\n ...(payload.body && {\n body: isBinaryData\n ? payload.body\n : JSON.stringify(payload.body, (_key, value) => (value === undefined ? null : value))\n }),\n ...(!localCfg.key && { credentials: 'same-origin' }),\n method: payload.method ?? 'get',\n headers: {\n Accept: 'application/json',\n ...(localCfg.key && { AuthenticationToken: localCfg.key }),\n ...(!isBinaryData && { 'Content-Type': 'application/json' })\n }\n });\n let res = (await interceptRequest(request, payload)) ?? request;\n if (!(res instanceof Response)) {\n res = requestOptions?.signal ? await fetch(res, { signal: requestOptions.signal } ) : await fetch(res);\n }\n res = (await interceptResponse(res)) ?? res;\n\n if (res.ok) {\n data =\n payload.forceBlob || !res.headers?.get('content-type')?.includes('application/json')\n ? await res.blob()\n : await res.json();\n } else {\n data = res.headers?.get('content-type')?.includes('application/json')\n ? await res.json()\n : res;\n }\n\n // Check if response was successful\n if (!res.ok) {\n return Promise.reject(data);\n }\n }\n\n return payload.unwrap ? data.result : data;\n};\n\nconst _remove = (\n cfg: ServiceConfigWithoutMultiRequest | undefined,\n endpoint: string,\n { dryRun = false }: RemoveQuery = {},\n requestOptions?: RequestOptions\n) =>\n wrapResponse(() =>\n raw({ ...cfg, multiRequest: false }, endpoint, {\n method: 'DELETE',\n query: { dryRun }\n }, requestOptions).then(() => undefined)\n );\n\nconst _create = (cfg: ServiceConfigWithoutMultiRequest | undefined, endpoint: string, data: any, requestOptions?: RequestOptions) =>\n wrapResponse(() =>\n raw({ ...cfg, multiRequest: false }, endpoint, {\n method: 'POST',\n body: data\n }, requestOptions)\n );\n\nconst _update = (\n cfg: ServiceConfigWithoutMultiRequest | undefined,\n endpoint: string,\n data: any,\n { ignoreMissingProperties, dryRun = false }: UpdateQuery = {},\n requestOptions?: RequestOptions\n) =>\n wrapResponse(() =>\n raw({ ...cfg, multiRequest: false }, endpoint, {\n method: 'PUT',\n body: data,\n query: {\n ignoreMissingProperties:\n ignoreMissingProperties ?? cfg?.ignoreMissingProperties ?? globalConfig?.ignoreMissingProperties,\n dryRun\n }\n }, requestOptions)\n );\n\nconst _generic = (\n cfg: ServiceConfigWithoutMultiRequest | undefined,\n method: RequestPayloadMethod,\n endpoint: string,\n payload?: GenericQuery<any, any>,\n forceBlob?: boolean,\n requestOptions?: RequestOptions\n) =>\n{\n const usePost = cfg?.usePost ?? globalConfig?.usePost\n return wrapResponse(() =>\n raw({ ...cfg, multiRequest: false }, endpoint, {\n method: usePost ? 'POST' : method,\n forceBlob,\n ...(usePost && method === 'GET' ?\n { body: { ...payload?.params } }\n :\n { body: payload?.body, query: payload?.params } )\n }, requestOptions))\n};\n";
144
144
 
@@ -1155,6 +1155,7 @@ const generateArray = (values) => {
1155
1155
 
1156
1156
  // Only functions matching this regex are included in the generation.
1157
1157
  const FILTER_REGEX = /^(some|count|create|remove|unique|update)$/;
1158
+ const SOME_FILTER_REGEX = /^(some)$/;
1158
1159
  /**
1159
1160
  * Generates for each function a map with the entity-name as key and service type as value.
1160
1161
  * E.g. WServicesWith[Function] where [Function] may be something like "some" or "create".
@@ -1163,6 +1164,7 @@ const FILTER_REGEX = /^(some|count|create|remove|unique|update)$/;
1163
1164
  */
1164
1165
  const generateGroupedServices = (services) => {
1165
1166
  const entityDescriptors = new Map();
1167
+ const someQueryDescriptors = new Map();
1166
1168
  for (const service of services) {
1167
1169
  for (const fn of service.functions) {
1168
1170
  if (!FILTER_REGEX.test(fn.name)) {
@@ -1176,17 +1178,28 @@ const generateGroupedServices = (services) => {
1176
1178
  type: `${pascalCase(service.name)}Service_${pascalCase(fn.name)}`
1177
1179
  }
1178
1180
  ]);
1181
+ if (SOME_FILTER_REGEX.test(fn.name)) {
1182
+ someQueryDescriptors.set(fn.name, [
1183
+ ...(someQueryDescriptors.get(fn.name) ?? []),
1184
+ {
1185
+ name: service.name,
1186
+ required: true,
1187
+ type: `${pascalCase(service.name)}Service_${pascalCase(fn.name)}_Query`
1188
+ }
1189
+ ]);
1190
+ }
1179
1191
  }
1180
1192
  }
1181
- const descriptors = [...entityDescriptors.entries()];
1193
+ const entityDescriptorEntries = [...entityDescriptors.entries()];
1194
+ const someQueryDescriptorEntries = [...someQueryDescriptors.entries()];
1182
1195
  const typeGuards = [];
1183
- for (const [name] of descriptors) {
1196
+ for (const [name] of entityDescriptorEntries) {
1184
1197
  const constant = camelCase(`wServiceWith_${name}_Names`);
1185
1198
  const service = pascalCase(`WServiceWith_${name}`);
1186
1199
  const guard = `(service: string | undefined): service is ${service} =>\n${indent(`${constant}.includes(service as ${service});`)}`;
1187
1200
  typeGuards.push(`export const is${service} = ${guard}`);
1188
1201
  }
1189
- return generateStatements(...descriptors.map(([name, props]) => generateInterface(pascalCase(`WServicesWith_${name}`), props)), ...descriptors.map(([name]) => generateType(pascalCase(`WServiceWith_${name}`), `keyof ${pascalCase(`WServicesWith_${name}`)}`)), ...descriptors.map(([name, props]) => {
1202
+ return generateStatements(...entityDescriptorEntries.map(([name, props]) => generateInterface(pascalCase(`WServicesWith_${name}`), props)), ...entityDescriptorEntries.map(([name]) => generateType(pascalCase(`WServiceWith_${name}`), `keyof ${pascalCase(`WServicesWith_${name}`)}`)), ...someQueryDescriptorEntries.map(([name, props]) => generateInterface(pascalCase(`WServicesWith_${name}_Query`), props)), ...someQueryDescriptorEntries.map(([name]) => generateType(pascalCase(`WServiceWith_${name}_Query`), `keyof ${pascalCase(`WServicesWith_${name}_Query`)}`)), ...entityDescriptorEntries.map(([name, props]) => {
1190
1203
  const constant = camelCase(`wServiceWith_${name}_Names`);
1191
1204
  const type = pascalCase(`WServiceWith_${name}`);
1192
1205
  const value = generateArray(props.map((v) => v.name));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weclapp/sdk",
3
- "version": "2.0.0-dev.57",
3
+ "version": "2.0.0-dev.59",
4
4
  "description": "weclapp SDK Generator",
5
5
  "author": "weclapp",
6
6
  "sideEffects": false,