Common api - chores (#17051)
Remove refacto-common TODO --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@@ -27,6 +27,7 @@ import {
|
||||
import {
|
||||
computeBatchPath,
|
||||
computeDuplicatesResultPath,
|
||||
computeGroupByResultPath,
|
||||
computeManyResultPath,
|
||||
computeMergeManyResultPath,
|
||||
computeRestoreManyResultPath,
|
||||
@@ -161,6 +162,11 @@ export class OpenApiService {
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
paths[`/${item.namePlural}/groupBy`] = computeGroupByResultPath(
|
||||
item,
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
|
||||
return paths;
|
||||
}, schema.paths as OpenAPIV3_1.PathsObject);
|
||||
|
||||
+3
-3
@@ -60,8 +60,8 @@ describe('computeParameters', () => {
|
||||
expect(computeDepthParameters()).toEqual({
|
||||
name: 'depth',
|
||||
in: 'query',
|
||||
description: `Determines the level of nested related objects to include in the response.
|
||||
- 0: Primary object only
|
||||
description: `Determines the level of nested related objects to include in the response.
|
||||
- 0: Primary object only
|
||||
- 1: Primary object + direct relations`,
|
||||
required: false,
|
||||
schema: {
|
||||
@@ -77,7 +77,7 @@ describe('computeParameters', () => {
|
||||
expect(computeFilterParameters()).toEqual({
|
||||
name: 'filter',
|
||||
in: 'query',
|
||||
description: `Format: field[COMPARATOR]:value,field2[COMPARATOR]:value2
|
||||
description: `Format: field[COMPARATOR]:value,field2[COMPARATOR]:value2
|
||||
Refer to the filter section at the top of the page for more details.`,
|
||||
required: false,
|
||||
schema: {
|
||||
|
||||
@@ -7,15 +7,20 @@ import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfa
|
||||
|
||||
import { generateRandomFieldValue } from 'src/engine/core-modules/open-api/utils/generate-random-field-value.util';
|
||||
import {
|
||||
computeAggregateParameters,
|
||||
computeDepthParameters,
|
||||
computeEndingBeforeParameters,
|
||||
computeFilterParameters,
|
||||
computeGroupByParameters,
|
||||
computeIdPathParameter,
|
||||
computeIncludeRecordsSampleParameters,
|
||||
computeLimitParameters,
|
||||
computeOrderByForRecordsParameters,
|
||||
computeOrderByParameters,
|
||||
computeSoftDeleteParameters,
|
||||
computeStartingAfterParameters,
|
||||
computeUpsertParameters,
|
||||
computeViewIdParameters,
|
||||
} from 'src/engine/core-modules/open-api/utils/parameters.utils';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -277,6 +282,11 @@ export const computeParameterComponents = (
|
||||
softDelete: computeSoftDeleteParameters(),
|
||||
orderBy: computeOrderByParameters(),
|
||||
limit: computeLimitParameters(fromMetadata),
|
||||
groupBy: computeGroupByParameters(),
|
||||
viewId: computeViewIdParameters(),
|
||||
aggregate: computeAggregateParameters(),
|
||||
includeRecordsSample: computeIncludeRecordsSampleParameters(),
|
||||
orderByForRecords: computeOrderByForRecordsParameters(),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ export const computeDepthParameters = (): OpenAPIV3_1.ParameterObject => {
|
||||
return {
|
||||
name: 'depth',
|
||||
in: 'query',
|
||||
description: `Determines the level of nested related objects to include in the response.
|
||||
- 0: Primary object only
|
||||
description: `Determines the level of nested related objects to include in the response.
|
||||
- 0: Primary object only
|
||||
- 1: Primary object + direct relations`,
|
||||
required: false,
|
||||
schema: {
|
||||
@@ -93,7 +93,7 @@ export const computeFilterParameters = (): OpenAPIV3_1.ParameterObject => {
|
||||
return {
|
||||
name: 'filter',
|
||||
in: 'query',
|
||||
description: `Format: field[COMPARATOR]:value,field2[COMPARATOR]:value2
|
||||
description: `Format: field[COMPARATOR]:value,field2[COMPARATOR]:value2
|
||||
Refer to the filter section at the top of the page for more details.`,
|
||||
required: false,
|
||||
schema: {
|
||||
@@ -157,3 +157,98 @@ export const computeIdPathParameter = (): OpenAPIV3_1.ParameterObject => {
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const computeGroupByParameters = (): OpenAPIV3_1.ParameterObject => {
|
||||
return {
|
||||
name: 'group_by',
|
||||
in: 'query',
|
||||
description: `Array of fields to group by. Each element can specify a field and optionally a subfield or granularity for date fields.`,
|
||||
required: true,
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
examples: {
|
||||
simple: {
|
||||
value: '[{"updatedAt": true}]',
|
||||
summary: 'Group by a single field',
|
||||
},
|
||||
subfield: {
|
||||
value: '[{"assignee": {"name": true}}]',
|
||||
summary: 'Group by a relation field subfield',
|
||||
},
|
||||
dateGranularity: {
|
||||
value: '[{"createdAt": {"granularity": "MONTH"}}]',
|
||||
summary: 'Group by date with granularity (DAY, WEEK, MONTH, YEAR)',
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const computeViewIdParameters = (): OpenAPIV3_1.ParameterObject => {
|
||||
return {
|
||||
name: 'view_id',
|
||||
in: 'query',
|
||||
description: 'View ID to apply filters from.',
|
||||
required: false,
|
||||
schema: {
|
||||
type: 'string',
|
||||
format: 'uuid',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const computeIncludeRecordsSampleParameters =
|
||||
(): OpenAPIV3_1.ParameterObject => {
|
||||
return {
|
||||
name: 'include_records_sample',
|
||||
in: 'query',
|
||||
description:
|
||||
'If true, includes a sample of records for each group in the response.',
|
||||
required: false,
|
||||
schema: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const computeAggregateParameters = (): OpenAPIV3_1.ParameterObject => {
|
||||
return {
|
||||
name: 'aggregate',
|
||||
in: 'query',
|
||||
description: `Array of aggregate operations to compute for each group.`,
|
||||
required: false,
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
examples: {
|
||||
count: {
|
||||
value: '["countNotEmptyId"]',
|
||||
summary: 'Count non-empty IDs in each group',
|
||||
},
|
||||
multiple: {
|
||||
value: '["countNotEmptyId", "sumAmount"]',
|
||||
summary: 'Multiple aggregate operations',
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const computeOrderByForRecordsParameters =
|
||||
(): OpenAPIV3_1.ParameterObject => {
|
||||
return {
|
||||
name: 'order_by_for_records',
|
||||
in: 'query',
|
||||
description: `Order by clause for records within each group. Only applicable when include_records_sample is true.`,
|
||||
required: false,
|
||||
schema: {
|
||||
type: 'string',
|
||||
},
|
||||
examples: {
|
||||
simple: {
|
||||
value: 'createdAt',
|
||||
summary: 'Order records by createdAt',
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
getFindDuplicatesResponse200,
|
||||
getFindManyResponse200,
|
||||
getFindOneResponse200,
|
||||
getGroupByResponse200,
|
||||
getJsonResponse,
|
||||
getMergeManyResponse200,
|
||||
getRestoreManyResponse200,
|
||||
@@ -325,3 +326,37 @@ export const computeMergeManyResultPath = (
|
||||
},
|
||||
} as OpenAPIV3_1.PathItemObject;
|
||||
};
|
||||
|
||||
export const computeGroupByResultPath = (
|
||||
item: Pick<FlatObjectMetadata, 'nameSingular' | 'namePlural'>,
|
||||
_flatObjectMetadataMaps: Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatObjectMetadataMaps'
|
||||
>['flatObjectMetadataMaps'],
|
||||
_flatFieldMetadataMaps: Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatFieldMetadataMaps'
|
||||
>['flatFieldMetadataMaps'],
|
||||
): OpenAPIV3_1.PathItemObject => {
|
||||
return {
|
||||
get: {
|
||||
tags: [item.namePlural],
|
||||
summary: `Group By ${item.namePlural}`,
|
||||
description: `Groups **${item.namePlural}** by specified fields and optionally computes aggregate values for each group.`,
|
||||
operationId: `groupBy${capitalize(item.namePlural)}`,
|
||||
parameters: [
|
||||
{ $ref: '#/components/parameters/groupBy' },
|
||||
{ $ref: '#/components/parameters/filter' },
|
||||
{ $ref: '#/components/parameters/orderBy' },
|
||||
{ $ref: '#/components/parameters/limit' },
|
||||
{ $ref: '#/components/parameters/viewId' },
|
||||
{ $ref: '#/components/parameters/aggregate' },
|
||||
{ $ref: '#/components/parameters/includeRecordsSample' },
|
||||
{ $ref: '#/components/parameters/orderByForRecords' },
|
||||
],
|
||||
responses: {
|
||||
'200': getGroupByResponse200(item),
|
||||
},
|
||||
},
|
||||
} as OpenAPIV3_1.PathItemObject;
|
||||
};
|
||||
|
||||
@@ -468,3 +468,57 @@ export const getMergeManyResponse200 = (
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const getGroupByResponse200 = (
|
||||
item: Pick<FlatObjectMetadata, 'nameSingular' | 'namePlural'>,
|
||||
) => {
|
||||
const schemaRef = `#/components/schemas/${capitalize(
|
||||
item.nameSingular,
|
||||
)}ForResponse`;
|
||||
|
||||
return {
|
||||
description: 'Successful operation',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
data: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
[`${item.namePlural}GroupBy`]: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
groupByDimensionValues: {
|
||||
type: 'array',
|
||||
description:
|
||||
'Array of values representing each dimension in the group',
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
records: {
|
||||
type: 'array',
|
||||
description:
|
||||
'Sample of records for this group (only present when include_records_sample is true)',
|
||||
items: {
|
||||
$ref: schemaRef,
|
||||
},
|
||||
},
|
||||
},
|
||||
additionalProperties: {
|
||||
type: 'number',
|
||||
description: 'Aggregate values (e.g., countNotEmptyId)',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user