5582 get httpsapitwentycomrestmetadata objects filters dont work (#5906)

- Remove filters from metadata rest api
- add limite before and after parameters for metadata
- remove update from metadata relations
- fix typing issue
- fix naming
- fix before parameter

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
martmull
2024-06-18 18:55:13 +02:00
committed by GitHub
parent dbaa787d19
commit 6fd8dab552
87 changed files with 701 additions and 567 deletions

View File

@ -2,7 +2,7 @@ import { Controller, Post, Req, Res } from '@nestjs/common';
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import { RestApiCoreService } from 'src/engine/api/rest/services/rest-api-core.service'; import { RestApiCoreService } from 'src/engine/api/rest/core/rest-api-core.service';
import { cleanGraphQLResponse } from 'src/engine/api/rest/utils/clean-graphql-response.utils'; import { cleanGraphQLResponse } from 'src/engine/api/rest/utils/clean-graphql-response.utils';
@Controller('rest/batch/*') @Controller('rest/batch/*')

View File

@ -11,7 +11,7 @@ import {
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import { RestApiCoreService } from 'src/engine/api/rest/services/rest-api-core.service'; import { RestApiCoreService } from 'src/engine/api/rest/core/rest-api-core.service';
import { cleanGraphQLResponse } from 'src/engine/api/rest/utils/clean-graphql-response.utils'; import { cleanGraphQLResponse } from 'src/engine/api/rest/utils/clean-graphql-response.utils';
@Controller('rest/*') @Controller('rest/*')

View File

@ -2,24 +2,24 @@ import { BadRequestException, Injectable } from '@nestjs/common';
import { Request } from 'express'; import { Request } from 'express';
import { DeleteQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/delete-query.factory'; import { DeleteQueryFactory } from 'src/engine/api/rest/core/query-builder/factories/delete-query.factory';
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
import { TokenService } from 'src/engine/core-modules/auth/services/token.service'; import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
import { CreateOneQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/create-one-query.factory'; import { CreateOneQueryFactory } from 'src/engine/api/rest/core/query-builder/factories/create-one-query.factory';
import { UpdateQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/update-query.factory'; import { UpdateQueryFactory } from 'src/engine/api/rest/core/query-builder/factories/update-query.factory';
import { FindOneQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/find-one-query.factory'; import { FindOneQueryFactory } from 'src/engine/api/rest/core/query-builder/factories/find-one-query.factory';
import { FindManyQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/find-many-query.factory'; import { FindManyQueryFactory } from 'src/engine/api/rest/core/query-builder/factories/find-many-query.factory';
import { DeleteVariablesFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/delete-variables.factory'; import { DeleteVariablesFactory } from 'src/engine/api/rest/core/query-builder/factories/delete-variables.factory';
import { CreateVariablesFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/create-variables.factory'; import { CreateVariablesFactory } from 'src/engine/api/rest/core/query-builder/factories/create-variables.factory';
import { UpdateVariablesFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/update-variables.factory'; import { UpdateVariablesFactory } from 'src/engine/api/rest/core/query-builder/factories/update-variables.factory';
import { GetVariablesFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/get-variables.factory'; import { GetVariablesFactory } from 'src/engine/api/rest/core/query-builder/factories/get-variables.factory';
import { parseCorePath } from 'src/engine/api/rest/rest-api-core-query-builder/utils/path-parsers/parse-core-path.utils'; import { parseCorePath } from 'src/engine/api/rest/core/query-builder/utils/path-parsers/parse-core-path.utils';
import { computeDepth } from 'src/engine/api/rest/rest-api-core-query-builder/utils/compute-depth.utils'; import { computeDepth } from 'src/engine/api/rest/core/query-builder/utils/compute-depth.utils';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { Query } from 'src/engine/api/rest/types/query.type'; import { Query } from 'src/engine/api/rest/core/types/query.type';
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
import { CreateManyQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/create-many-query.factory'; import { CreateManyQueryFactory } from 'src/engine/api/rest/core/query-builder/factories/create-many-query.factory';
import { parseCoreBatchPath } from 'src/engine/api/rest/rest-api-core-query-builder/utils/path-parsers/parse-core-batch-path.utils'; import { parseCoreBatchPath } from 'src/engine/api/rest/core/query-builder/utils/path-parsers/parse-core-batch-path.utils';
@Injectable() @Injectable()
export class CoreQueryBuilderFactory { export class CoreQueryBuilderFactory {

View File

@ -1,7 +1,7 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { CoreQueryBuilderFactory } from 'src/engine/api/rest/rest-api-core-query-builder/core-query-builder.factory'; import { CoreQueryBuilderFactory } from 'src/engine/api/rest/core/query-builder/core-query-builder.factory';
import { coreQueryBuilderFactories } from 'src/engine/api/rest/rest-api-core-query-builder/factories/factories'; import { coreQueryBuilderFactories } from 'src/engine/api/rest/core/query-builder/factories/factories';
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
import { AuthModule } from 'src/engine/core-modules/auth/auth.module'; import { AuthModule } from 'src/engine/core-modules/auth/auth.module';

View File

@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { capitalize } from 'src/utils/capitalize'; import { capitalize } from 'src/utils/capitalize';
import { mapFieldMetadataToGraphqlQuery } from 'src/engine/api/rest/rest-api-core-query-builder/utils/map-field-metadata-to-graphql-query.utils'; import { mapFieldMetadataToGraphqlQuery } from 'src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils';
@Injectable() @Injectable()
export class CreateManyQueryFactory { export class CreateManyQueryFactory {

View File

@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { capitalize } from 'src/utils/capitalize'; import { capitalize } from 'src/utils/capitalize';
import { mapFieldMetadataToGraphqlQuery } from 'src/engine/api/rest/rest-api-core-query-builder/utils/map-field-metadata-to-graphql-query.utils'; import { mapFieldMetadataToGraphqlQuery } from 'src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils';
@Injectable() @Injectable()
export class CreateOneQueryFactory { export class CreateOneQueryFactory {

View File

@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
import { Request } from 'express'; import { Request } from 'express';
import { QueryVariables } from 'src/engine/api/rest/types/query-variables.type'; import { QueryVariables } from 'src/engine/api/rest/core/types/query-variables.type';
@Injectable() @Injectable()
export class CreateVariablesFactory { export class CreateVariablesFactory {

View File

@ -1,6 +1,6 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { QueryVariables } from 'src/engine/api/rest/types/query-variables.type'; import { QueryVariables } from 'src/engine/api/rest/core/types/query-variables.type';
@Injectable() @Injectable()
export class DeleteVariablesFactory { export class DeleteVariablesFactory {

View File

@ -0,0 +1,25 @@
import { DeleteQueryFactory } from 'src/engine/api/rest/core/query-builder/factories/delete-query.factory';
import { CreateOneQueryFactory } from 'src/engine/api/rest/core/query-builder/factories/create-one-query.factory';
import { UpdateQueryFactory } from 'src/engine/api/rest/core/query-builder/factories/update-query.factory';
import { FindOneQueryFactory } from 'src/engine/api/rest/core/query-builder/factories/find-one-query.factory';
import { FindManyQueryFactory } from 'src/engine/api/rest/core/query-builder/factories/find-many-query.factory';
import { DeleteVariablesFactory } from 'src/engine/api/rest/core/query-builder/factories/delete-variables.factory';
import { CreateVariablesFactory } from 'src/engine/api/rest/core/query-builder/factories/create-variables.factory';
import { UpdateVariablesFactory } from 'src/engine/api/rest/core/query-builder/factories/update-variables.factory';
import { GetVariablesFactory } from 'src/engine/api/rest/core/query-builder/factories/get-variables.factory';
import { CreateManyQueryFactory } from 'src/engine/api/rest/core/query-builder/factories/create-many-query.factory';
import { inputFactories } from 'src/engine/api/rest/input-factories/factories';
export const coreQueryBuilderFactories = [
DeleteQueryFactory,
CreateOneQueryFactory,
CreateManyQueryFactory,
UpdateQueryFactory,
FindOneQueryFactory,
FindManyQueryFactory,
DeleteVariablesFactory,
CreateVariablesFactory,
UpdateVariablesFactory,
GetVariablesFactory,
...inputFactories,
];

View File

@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { capitalize } from 'src/utils/capitalize'; import { capitalize } from 'src/utils/capitalize';
import { mapFieldMetadataToGraphqlQuery } from 'src/engine/api/rest/rest-api-core-query-builder/utils/map-field-metadata-to-graphql-query.utils'; import { mapFieldMetadataToGraphqlQuery } from 'src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils';
@Injectable() @Injectable()
export class FindManyQueryFactory { export class FindManyQueryFactory {
@ -17,10 +17,16 @@ export class FindManyQueryFactory {
$orderBy: [${objectNameSingular}OrderByInput], $orderBy: [${objectNameSingular}OrderByInput],
$startingAfter: String, $startingAfter: String,
$endingBefore: String, $endingBefore: String,
$limit: Int = 60 $first: Int,
$last: Int
) { ) {
${objectNamePlural}( ${objectNamePlural}(
filter: $filter, orderBy: $orderBy, first: $limit, after: $startingAfter, before: $endingBefore filter: $filter,
orderBy: $orderBy,
first: $first,
last: $last,
after: $startingAfter,
before: $endingBefore
) { ) {
edges { edges {
node { node {

View File

@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { capitalize } from 'src/utils/capitalize'; import { capitalize } from 'src/utils/capitalize';
import { mapFieldMetadataToGraphqlQuery } from 'src/engine/api/rest/rest-api-core-query-builder/utils/map-field-metadata-to-graphql-query.utils'; import { mapFieldMetadataToGraphqlQuery } from 'src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils';
@Injectable() @Injectable()
export class FindOneQueryFactory { export class FindOneQueryFactory {

View File

@ -0,0 +1,44 @@
import { Injectable } from '@nestjs/common';
import { Request } from 'express';
import { LimitInputFactory } from 'src/engine/api/rest/input-factories/limit-input.factory';
import { OrderByInputFactory } from 'src/engine/api/rest/input-factories/order-by-input.factory';
import { FilterInputFactory } from 'src/engine/api/rest/input-factories/filter-input.factory';
import { QueryVariables } from 'src/engine/api/rest/core/types/query-variables.type';
import { EndingBeforeInputFactory } from 'src/engine/api/rest/input-factories/ending-before-input.factory';
import { StartingAfterInputFactory } from 'src/engine/api/rest/input-factories/starting-after-input.factory';
@Injectable()
export class GetVariablesFactory {
constructor(
private readonly startingAfterInputFactory: StartingAfterInputFactory,
private readonly endingBeforeInputFactory: EndingBeforeInputFactory,
private readonly limitInputFactory: LimitInputFactory,
private readonly orderByInputFactory: OrderByInputFactory,
private readonly filterInputFactory: FilterInputFactory,
) {}
create(
id: string | undefined,
request: Request,
objectMetadata,
): QueryVariables {
if (id) {
return { filter: { id: { eq: id } } };
}
const limit = this.limitInputFactory.create(request);
const endingBefore = this.endingBeforeInputFactory.create(request);
const startingAfter = this.startingAfterInputFactory.create(request);
return {
filter: this.filterInputFactory.create(request, objectMetadata),
orderBy: this.orderByInputFactory.create(request, objectMetadata),
first: !endingBefore ? limit : undefined,
last: endingBefore ? limit : undefined,
startingAfter,
endingBefore,
};
}
}

View File

@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { capitalize } from 'src/utils/capitalize'; import { capitalize } from 'src/utils/capitalize';
import { mapFieldMetadataToGraphqlQuery } from 'src/engine/api/rest/rest-api-core-query-builder/utils/map-field-metadata-to-graphql-query.utils'; import { mapFieldMetadataToGraphqlQuery } from 'src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils';
@Injectable() @Injectable()
export class UpdateQueryFactory { export class UpdateQueryFactory {

View File

@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
import { Request } from 'express'; import { Request } from 'express';
import { QueryVariables } from 'src/engine/api/rest/types/query-variables.type'; import { QueryVariables } from 'src/engine/api/rest/core/types/query-variables.type';
@Injectable() @Injectable()
export class UpdateVariablesFactory { export class UpdateVariablesFactory {

View File

@ -1,6 +1,6 @@
import { objectMetadataItemMock } from 'src/engine/api/__mocks__/object-metadata-item.mock'; import { objectMetadataItemMock } from 'src/engine/api/__mocks__/object-metadata-item.mock';
import { checkFields } from 'src/engine/api/rest/rest-api-core-query-builder/utils/check-fields.utils'; import { checkFields } from 'src/engine/api/rest/core/query-builder/utils/check-fields.utils';
import { checkArrayFields } from 'src/engine/api/rest/rest-api-core-query-builder/utils/check-order-by.utils'; import { checkArrayFields } from 'src/engine/api/rest/core/query-builder/utils/check-order-by.utils';
describe('checkFields', () => { describe('checkFields', () => {
it('should check field types', () => { it('should check field types', () => {

View File

@ -1,4 +1,4 @@
import { computeDepth } from 'src/engine/api/rest/rest-api-core-query-builder/utils/compute-depth.utils'; import { computeDepth } from 'src/engine/api/rest/core/query-builder/utils/compute-depth.utils';
describe('computeDepth', () => { describe('computeDepth', () => {
it('should compute depth from query', () => { it('should compute depth from query', () => {

View File

@ -1,6 +1,6 @@
import { objectMetadataItemMock } from 'src/engine/api/__mocks__/object-metadata-item.mock'; import { objectMetadataItemMock } from 'src/engine/api/__mocks__/object-metadata-item.mock';
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { getFieldType } from 'src/engine/api/rest/rest-api-core-query-builder/utils/get-field-type.utils'; import { getFieldType } from 'src/engine/api/rest/core/query-builder/utils/get-field-type.utils';
describe('getFieldType', () => { describe('getFieldType', () => {
it('should get field type', () => { it('should get field type', () => {

View File

@ -5,7 +5,7 @@ import {
fieldTextMock, fieldTextMock,
objectMetadataItemMock, objectMetadataItemMock,
} from 'src/engine/api/__mocks__/object-metadata-item.mock'; } from 'src/engine/api/__mocks__/object-metadata-item.mock';
import { mapFieldMetadataToGraphqlQuery } from 'src/engine/api/rest/rest-api-core-query-builder/utils/map-field-metadata-to-graphql-query.utils'; import { mapFieldMetadataToGraphqlQuery } from 'src/engine/api/rest/core/query-builder/utils/map-field-metadata-to-graphql-query.utils';
describe('mapFieldMetadataToGraphqlQuery', () => { describe('mapFieldMetadataToGraphqlQuery', () => {
it('should map properly', () => { it('should map properly', () => {

View File

@ -1,4 +1,4 @@
import { addDefaultConjunctionIfMissing } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/add-default-conjunction.utils'; import { addDefaultConjunctionIfMissing } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/add-default-conjunction.utils';
describe('addDefaultConjunctionIfMissing', () => { describe('addDefaultConjunctionIfMissing', () => {
it('should add default conjunction if missing', () => { it('should add default conjunction if missing', () => {

View File

@ -1,4 +1,4 @@
import { checkFilterEnumValues } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/check-filter-enum-values'; import { checkFilterEnumValues } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/check-filter-enum-values';
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { import {
fieldSelectMock, fieldSelectMock,

View File

@ -1,4 +1,4 @@
import { checkFilterQuery } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/check-filter-query.utils'; import { checkFilterQuery } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/check-filter-query.utils';
describe('checkFilterQuery', () => { describe('checkFilterQuery', () => {
it('should check filter query', () => { it('should check filter query', () => {

View File

@ -1,5 +1,5 @@
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { formatFieldValue } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/format-field-values.utils'; import { formatFieldValue } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/format-field-values.utils';
describe('formatFieldValue', () => { describe('formatFieldValue', () => {
it('should format fieldNumber value', () => { it('should format fieldNumber value', () => {

View File

@ -1,4 +1,4 @@
import { parseBaseFilter } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/parse-base-filter.utils'; import { parseBaseFilter } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/parse-base-filter.utils';
describe('parseBaseFilter', () => { describe('parseBaseFilter', () => {
it('should parse simple filter string test 1', () => { it('should parse simple filter string test 1', () => {

View File

@ -1,4 +1,4 @@
import { parseFilterContent } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/parse-filter-content.utils'; import { parseFilterContent } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/parse-filter-content.utils';
describe('parseFilterContent', () => { describe('parseFilterContent', () => {
it('should parse query filter test 1', () => { it('should parse query filter test 1', () => {

View File

@ -1,5 +1,5 @@
import { objectMetadataItemMock } from 'src/engine/api/__mocks__/object-metadata-item.mock'; import { objectMetadataItemMock } from 'src/engine/api/__mocks__/object-metadata-item.mock';
import { parseFilter } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/parse-filter.utils'; import { parseFilter } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/parse-filter.utils';
describe('parseFilter', () => { describe('parseFilter', () => {
it('should parse string filter test 1', () => { it('should parse string filter test 1', () => {

View File

@ -1,4 +1,4 @@
import { Conjunctions } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/parse-filter.utils'; import { Conjunctions } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/parse-filter.utils';
export const DEFAULT_CONJUNCTION = Conjunctions.and; export const DEFAULT_CONJUNCTION = Conjunctions.and;

View File

@ -1,7 +1,7 @@
import { BadRequestException } from '@nestjs/common'; import { BadRequestException } from '@nestjs/common';
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { FieldValue } from 'src/engine/api/rest/types/field-value.type'; import { FieldValue } from 'src/engine/api/rest/core/types/field-value.type';
export const formatFieldValue = ( export const formatFieldValue = (
value: string, value: string,

View File

@ -2,13 +2,13 @@ import { BadRequestException } from '@nestjs/common';
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
import { parseFilterContent } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/parse-filter-content.utils'; import { parseFilterContent } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/parse-filter-content.utils';
import { parseBaseFilter } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/parse-base-filter.utils'; import { parseBaseFilter } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/parse-base-filter.utils';
import { checkFields } from 'src/engine/api/rest/rest-api-core-query-builder/utils/check-fields.utils'; import { checkFields } from 'src/engine/api/rest/core/query-builder/utils/check-fields.utils';
import { formatFieldValue } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/format-field-values.utils'; import { formatFieldValue } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/format-field-values.utils';
import { FieldValue } from 'src/engine/api/rest/types/field-value.type'; import { FieldValue } from 'src/engine/api/rest/core/types/field-value.type';
import { checkFilterEnumValues } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/check-filter-enum-values'; import { checkFilterEnumValues } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/check-filter-enum-values';
import { getFieldType } from 'src/engine/api/rest/rest-api-core-query-builder/utils/get-field-type.utils'; import { getFieldType } from 'src/engine/api/rest/core/query-builder/utils/get-field-type.utils';
export enum Conjunctions { export enum Conjunctions {
or = 'or', or = 'or',

View File

@ -1,4 +1,4 @@
import { parseCoreBatchPath } from 'src/engine/api/rest/rest-api-core-query-builder/utils/path-parsers/parse-core-batch-path.utils'; import { parseCoreBatchPath } from 'src/engine/api/rest/core/query-builder/utils/path-parsers/parse-core-batch-path.utils';
describe('parseCoreBatchPath', () => { describe('parseCoreBatchPath', () => {
it('should parse object from request path', () => { it('should parse object from request path', () => {

View File

@ -1,4 +1,4 @@
import { parseCorePath } from 'src/engine/api/rest/rest-api-core-query-builder/utils/path-parsers/parse-core-path.utils'; import { parseCorePath } from 'src/engine/api/rest/core/query-builder/utils/path-parsers/parse-core-path.utils';
describe('parseCorePath', () => { describe('parseCorePath', () => {
it('should parse object from request path', () => { it('should parse object from request path', () => {

View File

@ -2,11 +2,11 @@ import { Injectable } from '@nestjs/common';
import { Request } from 'express'; import { Request } from 'express';
import { CoreQueryBuilderFactory } from 'src/engine/api/rest/rest-api-core-query-builder/core-query-builder.factory'; import { CoreQueryBuilderFactory } from 'src/engine/api/rest/core/query-builder/core-query-builder.factory';
import { import {
GraphqlApiType, GraphqlApiType,
RestApiService, RestApiService,
} from 'src/engine/api/rest/services/rest-api.service'; } from 'src/engine/api/rest/rest-api.service';
@Injectable() @Injectable()
export class RestApiCoreService { export class RestApiCoreService {

View File

@ -3,7 +3,8 @@ export type QueryVariables = {
data?: object | null; data?: object | null;
filter?: object; filter?: object;
orderBy?: object; orderBy?: object;
limit?: number; last?: number;
first?: number;
startingAfter?: string; startingAfter?: string;
endingBefore?: string; endingBefore?: string;
input?: object; input?: object;

View File

@ -0,0 +1,6 @@
import { QueryVariables } from 'src/engine/api/rest/core/types/query-variables.type';
export type Query = {
query: string;
variables: QueryVariables;
};

View File

@ -1,6 +1,6 @@
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
import { EndingBeforeInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/ending-before-input.factory'; import { EndingBeforeInputFactory } from 'src/engine/api/rest/input-factories/ending-before-input.factory';
describe('EndingBeforeInputFactory', () => { describe('EndingBeforeInputFactory', () => {
let service: EndingBeforeInputFactory; let service: EndingBeforeInputFactory;

View File

@ -1,7 +1,7 @@
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
import { objectMetadataItemMock } from 'src/engine/api/__mocks__/object-metadata-item.mock'; import { objectMetadataItemMock } from 'src/engine/api/__mocks__/object-metadata-item.mock';
import { FilterInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-input.factory'; import { FilterInputFactory } from 'src/engine/api/rest/input-factories/filter-input.factory';
describe('FilterInputFactory', () => { describe('FilterInputFactory', () => {
const objectMetadata = { objectMetadataItem: objectMetadataItemMock }; const objectMetadata = { objectMetadataItem: objectMetadataItemMock };

View File

@ -1,6 +1,6 @@
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
import { LimitInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/limit-input.factory'; import { LimitInputFactory } from 'src/engine/api/rest/input-factories/limit-input.factory';
describe('LimitInputFactory', () => { describe('LimitInputFactory', () => {
let service: LimitInputFactory; let service: LimitInputFactory;

View File

@ -3,7 +3,7 @@ import { Test, TestingModule } from '@nestjs/testing';
import { OrderByDirection } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; import { OrderByDirection } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface';
import { objectMetadataItemMock } from 'src/engine/api/__mocks__/object-metadata-item.mock'; import { objectMetadataItemMock } from 'src/engine/api/__mocks__/object-metadata-item.mock';
import { OrderByInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/order-by-input.factory'; import { OrderByInputFactory } from 'src/engine/api/rest/input-factories/order-by-input.factory';
describe('OrderByInputFactory', () => { describe('OrderByInputFactory', () => {
const objectMetadata = { objectMetadataItem: objectMetadataItemMock }; const objectMetadata = { objectMetadataItem: objectMetadataItemMock };

View File

@ -1,6 +1,6 @@
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
import { StartingAfterInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/starting-after-input.factory'; import { StartingAfterInputFactory } from 'src/engine/api/rest/input-factories/starting-after-input.factory';
describe('StartingAfterInputFactory', () => { describe('StartingAfterInputFactory', () => {
let service: StartingAfterInputFactory; let service: StartingAfterInputFactory;

View File

@ -0,0 +1,13 @@
import { StartingAfterInputFactory } from 'src/engine/api/rest/input-factories/starting-after-input.factory';
import { EndingBeforeInputFactory } from 'src/engine/api/rest/input-factories/ending-before-input.factory';
import { LimitInputFactory } from 'src/engine/api/rest/input-factories/limit-input.factory';
import { OrderByInputFactory } from 'src/engine/api/rest/input-factories/order-by-input.factory';
import { FilterInputFactory } from 'src/engine/api/rest/input-factories/filter-input.factory';
export const inputFactories = [
StartingAfterInputFactory,
EndingBeforeInputFactory,
LimitInputFactory,
OrderByInputFactory,
FilterInputFactory,
];

View File

@ -2,10 +2,10 @@ import { Injectable } from '@nestjs/common';
import { Request } from 'express'; import { Request } from 'express';
import { addDefaultConjunctionIfMissing } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/add-default-conjunction.utils'; import { addDefaultConjunctionIfMissing } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/add-default-conjunction.utils';
import { checkFilterQuery } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/check-filter-query.utils'; import { checkFilterQuery } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/check-filter-query.utils';
import { parseFilter } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/parse-filter.utils'; import { parseFilter } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/parse-filter.utils';
import { FieldValue } from 'src/engine/api/rest/types/field-value.type'; import { FieldValue } from 'src/engine/api/rest/core/types/field-value.type';
@Injectable() @Injectable()
export class FilterInputFactory { export class FilterInputFactory {

View File

@ -4,9 +4,9 @@ import { Request } from 'express';
@Injectable() @Injectable()
export class LimitInputFactory { export class LimitInputFactory {
create(request: Request): number { create(request: Request, defaultLimit = 60): number {
if (!request.query.limit) { if (!request.query.limit) {
return 60; return defaultLimit;
} }
const limit = +request.query.limit; const limit = +request.query.limit;

View File

@ -7,7 +7,7 @@ import {
RecordOrderBy, RecordOrderBy,
} from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface';
import { checkArrayFields } from 'src/engine/api/rest/rest-api-core-query-builder/utils/check-order-by.utils'; import { checkArrayFields } from 'src/engine/api/rest/core/query-builder/utils/check-order-by.utils';
export const DEFAULT_ORDER_DIRECTION = OrderByDirection.AscNullsFirst; export const DEFAULT_ORDER_DIRECTION = OrderByDirection.AscNullsFirst;

View File

@ -0,0 +1,24 @@
import { Injectable } from '@nestjs/common';
import { capitalize } from 'src/utils/capitalize';
import { fetchMetadataFields } from 'src/engine/api/rest/metadata/query-builder/utils/fetch-metadata-fields.utils';
@Injectable()
export class CreateMetadataQueryFactory {
create(objectNameSingular: string, objectNamePlural: string): string {
const objectNameCapitalized = capitalize(objectNameSingular);
const fields = fetchMetadataFields(objectNamePlural);
return `
mutation Create${objectNameCapitalized}($input: CreateOne${objectNameCapitalized}${
objectNameSingular === 'field' ? 'Metadata' : ''
}Input!) {
createOne${objectNameCapitalized}(input: $input) {
id
${fields}
}
}
`;
}
}

View File

@ -0,0 +1,18 @@
import { Injectable } from '@nestjs/common';
import { capitalize } from 'src/utils/capitalize';
@Injectable()
export class DeleteMetadataQueryFactory {
create(objectNameSingular: string): string {
const objectNameCapitalized = capitalize(objectNameSingular);
return `
mutation Delete${objectNameCapitalized}($input: DeleteOne${objectNameCapitalized}Input!) {
deleteOne${objectNameCapitalized}(input: $input) {
id
}
}
`;
}
}

View File

@ -0,0 +1,33 @@
import { Injectable } from '@nestjs/common';
import { capitalize } from 'src/utils/capitalize';
import { fetchMetadataFields } from 'src/engine/api/rest/metadata/query-builder/utils/fetch-metadata-fields.utils';
@Injectable()
export class FindManyMetadataQueryFactory {
create(objectNamePlural): string {
const fields = fetchMetadataFields(objectNamePlural);
return `
query FindMany${capitalize(objectNamePlural)}(
$paging: CursorPaging!
) {
${objectNamePlural}(
paging: $paging
) {
edges {
node {
id
${fields}
}
}
pageInfo {
hasNextPage
startCursor
endCursor
}
}
}
`;
}
}

View File

@ -0,0 +1,22 @@
import { Injectable } from '@nestjs/common';
import { capitalize } from 'src/utils/capitalize';
import { fetchMetadataFields } from 'src/engine/api/rest/metadata/query-builder/utils/fetch-metadata-fields.utils';
@Injectable()
export class FindOneMetadataQueryFactory {
create(objectNameSingular: string, objectNamePlural: string): string {
const fields = fetchMetadataFields(objectNamePlural);
return `
query FindOne${capitalize(objectNameSingular)}(
$id: UUID!,
) {
${objectNameSingular}(id: $id) {
id
${fields}
}
}
`;
}
}

View File

@ -0,0 +1,42 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { Request } from 'express';
import { LimitInputFactory } from 'src/engine/api/rest/input-factories/limit-input.factory';
import { EndingBeforeInputFactory } from 'src/engine/api/rest/input-factories/ending-before-input.factory';
import { StartingAfterInputFactory } from 'src/engine/api/rest/input-factories/starting-after-input.factory';
import { MetadataQueryVariables } from 'src/engine/api/rest/metadata/types/metadata-query-variables.type';
@Injectable()
export class GetMetadataVariablesFactory {
constructor(
private readonly startingAfterInputFactory: StartingAfterInputFactory,
private readonly endingBeforeInputFactory: EndingBeforeInputFactory,
private readonly limitInputFactory: LimitInputFactory,
) {}
create(id: string | undefined, request: Request): MetadataQueryVariables {
if (id) {
return { id };
}
const limit = this.limitInputFactory.create(request, 1000);
const before = this.endingBeforeInputFactory.create(request);
const after = this.startingAfterInputFactory.create(request);
if (before && after) {
throw new BadRequestException(
`Only one of 'endingBefore' and 'startingAfter' may be provided`,
);
}
return {
paging: {
first: !before ? limit : undefined,
last: before ? limit : undefined,
after,
before,
},
};
}
}

View File

@ -0,0 +1,17 @@
import { FindOneMetadataQueryFactory } from 'src/engine/api/rest/metadata/query-builder/factories/find-one-metadata-query.factory';
import { FindManyMetadataQueryFactory } from 'src/engine/api/rest/metadata/query-builder/factories/find-many-metadata-query.factory';
import { GetMetadataVariablesFactory } from 'src/engine/api/rest/metadata/query-builder/factories/get-metadata-variables.factory';
import { inputFactories } from 'src/engine/api/rest/input-factories/factories';
import { CreateMetadataQueryFactory } from 'src/engine/api/rest/metadata/query-builder/factories/create-metadata-query.factory';
import { UpdateMetadataQueryFactory } from 'src/engine/api/rest/metadata/query-builder/factories/update-metadata-query.factory';
import { DeleteMetadataQueryFactory } from 'src/engine/api/rest/metadata/query-builder/factories/delete-metadata-query.factory';
export const metadataQueryBuilderFactories = [
FindOneMetadataQueryFactory,
FindManyMetadataQueryFactory,
CreateMetadataQueryFactory,
DeleteMetadataQueryFactory,
UpdateMetadataQueryFactory,
GetMetadataVariablesFactory,
...inputFactories,
];

View File

@ -0,0 +1,24 @@
import { Injectable } from '@nestjs/common';
import { capitalize } from 'src/utils/capitalize';
import { fetchMetadataFields } from 'src/engine/api/rest/metadata/query-builder/utils/fetch-metadata-fields.utils';
@Injectable()
export class UpdateMetadataQueryFactory {
create(objectNameSingular: string, objectNamePlural: string): string {
const objectNameCapitalized = capitalize(objectNameSingular);
const fields = fetchMetadataFields(objectNamePlural);
return `
mutation Update${objectNameCapitalized}($input: UpdateOne${objectNameCapitalized}${
objectNameSingular === 'field' ? 'Metadata' : ''
}Input!) {
updateOne${objectNameCapitalized}(input: $input) {
id
${fields}
}
}
`;
}
}

View File

@ -0,0 +1,95 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { Request } from 'express';
import { GetMetadataVariablesFactory } from 'src/engine/api/rest/metadata/query-builder/factories/get-metadata-variables.factory';
import { FindOneMetadataQueryFactory } from 'src/engine/api/rest/metadata/query-builder/factories/find-one-metadata-query.factory';
import { FindManyMetadataQueryFactory } from 'src/engine/api/rest/metadata/query-builder/factories/find-many-metadata-query.factory';
import { parseMetadataPath } from 'src/engine/api/rest/metadata/query-builder/utils/parse-metadata-path.utils';
import { CreateMetadataQueryFactory } from 'src/engine/api/rest/metadata/query-builder/factories/create-metadata-query.factory';
import { UpdateMetadataQueryFactory } from 'src/engine/api/rest/metadata/query-builder/factories/update-metadata-query.factory';
import { DeleteMetadataQueryFactory } from 'src/engine/api/rest/metadata/query-builder/factories/delete-metadata-query.factory';
import { MetadataQuery } from 'src/engine/api/rest/metadata/types/metadata-query.type';
@Injectable()
export class MetadataQueryBuilderFactory {
constructor(
private readonly findOneQueryFactory: FindOneMetadataQueryFactory,
private readonly findManyQueryFactory: FindManyMetadataQueryFactory,
private readonly createQueryFactory: CreateMetadataQueryFactory,
private readonly updateQueryFactory: UpdateMetadataQueryFactory,
private readonly deleteQueryFactory: DeleteMetadataQueryFactory,
private readonly getMetadataVariablesFactory: GetMetadataVariablesFactory,
) {}
async get(request: Request): Promise<MetadataQuery> {
const { id, objectNameSingular, objectNamePlural } =
parseMetadataPath(request);
return {
query: id
? this.findOneQueryFactory.create(objectNameSingular, objectNamePlural)
: this.findManyQueryFactory.create(objectNamePlural),
variables: this.getMetadataVariablesFactory.create(id, request),
};
}
async create(request: Request): Promise<MetadataQuery> {
const { objectNameSingular, objectNamePlural } = parseMetadataPath(request);
return {
query: this.createQueryFactory.create(
objectNameSingular,
objectNamePlural,
),
variables: {
input: {
[objectNameSingular]: request.body,
},
},
};
}
async update(request: Request): Promise<MetadataQuery> {
const { objectNameSingular, objectNamePlural, id } =
parseMetadataPath(request);
if (!id) {
throw new BadRequestException(
`update ${objectNameSingular} query invalid. Id missing. eg: /rest/metadata/${objectNameSingular}/0d4389ef-ea9c-4ae8-ada1-1cddc440fb56`,
);
}
return {
query: this.updateQueryFactory.create(
objectNameSingular,
objectNamePlural,
),
variables: {
input: {
update: request.body,
id,
},
},
};
}
async delete(request: Request): Promise<MetadataQuery> {
const { objectNameSingular, id } = parseMetadataPath(request);
if (!id) {
throw new BadRequestException(
`delete ${objectNameSingular} query invalid. Id missing. eg: /rest/metadata/${objectNameSingular}/0d4389ef-ea9c-4ae8-ada1-1cddc440fb56`,
);
}
return {
query: this.deleteQueryFactory.create(objectNameSingular),
variables: {
input: {
id,
},
},
};
}
}

View File

@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { AuthModule } from 'src/engine/core-modules/auth/auth.module';
import { MetadataQueryBuilderFactory } from 'src/engine/api/rest/metadata/query-builder/metadata-query-builder.factory';
import { metadataQueryBuilderFactories } from 'src/engine/api/rest/metadata/query-builder/factories/metadata-factories';
@Module({
imports: [AuthModule],
providers: [...metadataQueryBuilderFactories, MetadataQueryBuilderFactory],
exports: [MetadataQueryBuilderFactory],
})
export class MetadataQueryBuilderModule {}

View File

@ -1,4 +1,4 @@
import { parseMetadataPath } from 'src/engine/api/rest/rest-api-core-query-builder/utils/path-parsers/parse-metadata-path.utils'; import { parseMetadataPath } from 'src/engine/api/rest/metadata/query-builder/utils/parse-metadata-path.utils';
describe('parseMetadataPath', () => { describe('parseMetadataPath', () => {
it('should parse object from request path with uuid', () => { it('should parse object from request path with uuid', () => {

View File

@ -0,0 +1,93 @@
export const fetchMetadataFields = (objectNamePlural: string) => {
const fields = `
type
name
label
description
icon
isCustom
isActive
isSystem
isNullable
createdAt
updatedAt
fromRelationMetadata {
id
relationType
toObjectMetadata {
id
dataSourceId
nameSingular
namePlural
isSystem
}
toFieldMetadataId
}
toRelationMetadata {
id
relationType
fromObjectMetadata {
id
dataSourceId
nameSingular
namePlural
isSystem
}
fromFieldMetadataId
}
defaultValue
options
`;
switch (objectNamePlural) {
case 'objects':
return `
dataSourceId
nameSingular
namePlural
labelSingular
labelPlural
description
icon
isCustom
isActive
isSystem
createdAt
updatedAt
labelIdentifierFieldMetadataId
imageIdentifierFieldMetadataId
fields(paging: { first: 1000 }) {
edges {
node {
id
${fields}
}
}
}
`;
case 'fields':
return fields;
case 'relations':
return `
relationType
fromObjectMetadata {
id
dataSourceId
nameSingular
namePlural
isSystem
}
fromObjectMetadataId
toObjectMetadata {
id
dataSourceId
nameSingular
namePlural
isSystem
}
toObjectMetadataId
fromFieldMetadataId
toFieldMetadataId
`;
}
};

View File

@ -11,7 +11,7 @@ import {
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import { RestApiMetadataService } from 'src/engine/api/rest/services/rest-api-metadata.service'; import { RestApiMetadataService } from 'src/engine/api/rest/metadata/rest-api-metadata.service';
import { cleanGraphQLResponse } from 'src/engine/api/rest/utils/clean-graphql-response.utils'; import { cleanGraphQLResponse } from 'src/engine/api/rest/utils/clean-graphql-response.utils';
@Controller('rest/metadata/*') @Controller('rest/metadata/*')

View File

@ -0,0 +1,63 @@
import { Injectable } from '@nestjs/common';
import { Request } from 'express';
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
import {
GraphqlApiType,
RestApiService,
} from 'src/engine/api/rest/rest-api.service';
import { MetadataQueryBuilderFactory } from 'src/engine/api/rest/metadata/query-builder/metadata-query-builder.factory';
@Injectable()
export class RestApiMetadataService {
constructor(
private readonly tokenService: TokenService,
private readonly metadataQueryBuilderFactory: MetadataQueryBuilderFactory,
private readonly restApiService: RestApiService,
) {}
async get(request: Request) {
await this.tokenService.validateToken(request);
const data = await this.metadataQueryBuilderFactory.get(request);
return await this.restApiService.call(
GraphqlApiType.METADATA,
request,
data,
);
}
async create(request: Request) {
await this.tokenService.validateToken(request);
const data = await this.metadataQueryBuilderFactory.create(request);
return await this.restApiService.call(
GraphqlApiType.METADATA,
request,
data,
);
}
async update(request: Request) {
await this.tokenService.validateToken(request);
const data = await this.metadataQueryBuilderFactory.update(request);
return await this.restApiService.call(
GraphqlApiType.METADATA,
request,
data,
);
}
async delete(request: Request) {
await this.tokenService.validateToken(request);
const data = await this.metadataQueryBuilderFactory.delete(request);
return await this.restApiService.call(
GraphqlApiType.METADATA,
request,
data,
);
}
}

View File

@ -0,0 +1,10 @@
export type MetadataQueryVariables = {
id?: string;
input?: object;
paging?: {
first?: number;
last?: number;
after?: string;
before?: string;
};
};

View File

@ -0,0 +1,6 @@
import { MetadataQueryVariables } from 'src/engine/api/rest/metadata/types/metadata-query-variables.type';
export type MetadataQuery = {
query: string;
variables: MetadataQueryVariables;
};

View File

@ -1,46 +0,0 @@
import { Test, TestingModule } from '@nestjs/testing';
import { CoreQueryBuilderFactory } from 'src/engine/api/rest/rest-api-core-query-builder/core-query-builder.factory';
import { DeleteQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/delete-query.factory';
import { CreateOneQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/create-one-query.factory';
import { CreateManyQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/create-many-query.factory';
import { UpdateQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/update-query.factory';
import { FindOneQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/find-one-query.factory';
import { FindManyQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/find-many-query.factory';
import { DeleteVariablesFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/delete-variables.factory';
import { CreateVariablesFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/create-variables.factory';
import { UpdateVariablesFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/update-variables.factory';
import { GetVariablesFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/get-variables.factory';
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
describe('CoreQueryBuilderFactory', () => {
let service: CoreQueryBuilderFactory;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
CoreQueryBuilderFactory,
{ provide: DeleteQueryFactory, useValue: {} },
{ provide: CreateOneQueryFactory, useValue: {} },
{ provide: CreateManyQueryFactory, useValue: {} },
{ provide: UpdateQueryFactory, useValue: {} },
{ provide: FindOneQueryFactory, useValue: {} },
{ provide: FindManyQueryFactory, useValue: {} },
{ provide: DeleteVariablesFactory, useValue: {} },
{ provide: CreateVariablesFactory, useValue: {} },
{ provide: UpdateVariablesFactory, useValue: {} },
{ provide: GetVariablesFactory, useValue: {} },
{ provide: ObjectMetadataService, useValue: {} },
{ provide: TokenService, useValue: {} },
{ provide: EnvironmentService, useValue: {} },
],
}).compile();
service = module.get<CoreQueryBuilderFactory>(CoreQueryBuilderFactory);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -1,33 +0,0 @@
import { DeleteQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/delete-query.factory';
import { CreateOneQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/create-one-query.factory';
import { UpdateQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/update-query.factory';
import { FindOneQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/find-one-query.factory';
import { FindManyQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/find-many-query.factory';
import { DeleteVariablesFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/delete-variables.factory';
import { CreateVariablesFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/create-variables.factory';
import { UpdateVariablesFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/update-variables.factory';
import { GetVariablesFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/get-variables.factory';
import { LimitInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/limit-input.factory';
import { OrderByInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/order-by-input.factory';
import { FilterInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-input.factory';
import { CreateManyQueryFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/create-many-query.factory';
import { StartingAfterInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/starting-after-input.factory';
import { EndingBeforeInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/ending-before-input.factory';
export const coreQueryBuilderFactories = [
DeleteQueryFactory,
CreateOneQueryFactory,
CreateManyQueryFactory,
UpdateQueryFactory,
FindOneQueryFactory,
FindManyQueryFactory,
DeleteVariablesFactory,
CreateVariablesFactory,
UpdateVariablesFactory,
GetVariablesFactory,
StartingAfterInputFactory,
EndingBeforeInputFactory,
LimitInputFactory,
OrderByInputFactory,
FilterInputFactory,
];

View File

@ -1,39 +0,0 @@
import { Injectable } from '@nestjs/common';
import { Request } from 'express';
import { LimitInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/limit-input.factory';
import { OrderByInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/order-by-input.factory';
import { FilterInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-input.factory';
import { QueryVariables } from 'src/engine/api/rest/types/query-variables.type';
import { EndingBeforeInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/ending-before-input.factory';
import { StartingAfterInputFactory } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/starting-after-input.factory';
@Injectable()
export class GetVariablesFactory {
constructor(
private readonly startingAfterInputFactory: StartingAfterInputFactory,
private readonly endingBeforeInputFactory: EndingBeforeInputFactory,
private readonly limitInputFactory: LimitInputFactory,
private readonly orderByInputFactory: OrderByInputFactory,
private readonly filterInputFactory: FilterInputFactory,
) {}
create(
id: string | undefined,
request: Request,
objectMetadata,
): QueryVariables {
if (id) {
return { filter: { id: { eq: id } } };
}
return {
filter: this.filterInputFactory.create(request, objectMetadata),
orderBy: this.orderByInputFactory.create(request, objectMetadata),
limit: this.limitInputFactory.create(request),
startingAfter: this.startingAfterInputFactory.create(request),
endingBefore: this.endingBeforeInputFactory.create(request),
};
}
}

View File

@ -1,23 +1,39 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { HttpModule } from '@nestjs/axios'; import { HttpModule } from '@nestjs/axios';
import { RestApiCoreController } from 'src/engine/api/rest/controllers/rest-api-core.controller'; import { RestApiCoreController } from 'src/engine/api/rest/core/controllers/rest-api-core.controller';
import { RestApiCoreService } from 'src/engine/api/rest/services/rest-api-core.service'; import { RestApiCoreService } from 'src/engine/api/rest/core/rest-api-core.service';
import { CoreQueryBuilderModule } from 'src/engine/api/rest/rest-api-core-query-builder/core-query-builder.module'; import { CoreQueryBuilderModule } from 'src/engine/api/rest/core/query-builder/core-query-builder.module';
import { AuthModule } from 'src/engine/core-modules/auth/auth.module'; import { AuthModule } from 'src/engine/core-modules/auth/auth.module';
import { RestApiMetadataController } from 'src/engine/api/rest/controllers/rest-api-metadata.controller'; import { RestApiMetadataController } from 'src/engine/api/rest/metadata/rest-api-metadata.controller';
import { RestApiMetadataService } from 'src/engine/api/rest/services/rest-api-metadata.service'; import { RestApiMetadataService } from 'src/engine/api/rest/metadata/rest-api-metadata.service';
import { RestApiCoreBatchController } from 'src/engine/api/rest/controllers/rest-api-core-batch.controller'; import { RestApiCoreBatchController } from 'src/engine/api/rest/core/controllers/rest-api-core-batch.controller';
import { RestApiService } from 'src/engine/api/rest/services/rest-api.service'; import { RestApiService } from 'src/engine/api/rest/rest-api.service';
import { EndingBeforeInputFactory } from 'src/engine/api/rest/input-factories/ending-before-input.factory';
import { LimitInputFactory } from 'src/engine/api/rest/input-factories/limit-input.factory';
import { StartingAfterInputFactory } from 'src/engine/api/rest/input-factories/starting-after-input.factory';
import { MetadataQueryBuilderModule } from 'src/engine/api/rest/metadata/query-builder/metadata-query-builder.module';
@Module({ @Module({
imports: [CoreQueryBuilderModule, AuthModule, HttpModule], imports: [
CoreQueryBuilderModule,
MetadataQueryBuilderModule,
AuthModule,
HttpModule,
],
controllers: [ controllers: [
RestApiMetadataController, RestApiMetadataController,
RestApiCoreBatchController, RestApiCoreBatchController,
RestApiCoreController, RestApiCoreController,
], ],
providers: [RestApiMetadataService, RestApiCoreService, RestApiService], providers: [
RestApiMetadataService,
RestApiCoreService,
RestApiService,
StartingAfterInputFactory,
EndingBeforeInputFactory,
LimitInputFactory,
],
exports: [RestApiMetadataService], exports: [RestApiMetadataService],
}) })
export class RestApiModule {} export class RestApiModule {}

View File

@ -4,7 +4,7 @@ import { HttpService } from '@nestjs/axios';
import { Request } from 'express'; import { Request } from 'express';
import { AxiosResponse } from 'axios'; import { AxiosResponse } from 'axios';
import { Query } from 'src/engine/api/rest/types/query.type'; import { Query } from 'src/engine/api/rest/core/types/query.type';
import { getServerUrl } from 'src/utils/get-server-url'; import { getServerUrl } from 'src/utils/get-server-url';
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
import { RestApiException } from 'src/engine/api/rest/errors/RestApiException'; import { RestApiException } from 'src/engine/api/rest/errors/RestApiException';

View File

@ -1,30 +0,0 @@
import { Test, TestingModule } from '@nestjs/testing';
import { RestApiCoreService } from 'src/engine/api/rest/services/rest-api-core.service';
import { CoreQueryBuilderFactory } from 'src/engine/api/rest/rest-api-core-query-builder/core-query-builder.factory';
import { RestApiService } from 'src/engine/api/rest/services/rest-api.service';
describe('RestApiCoreService', () => {
let service: RestApiCoreService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
RestApiCoreService,
{
provide: CoreQueryBuilderFactory,
useValue: {},
},
{
provide: RestApiService,
useValue: {},
},
],
}).compile();
service = module.get<RestApiCoreService>(RestApiCoreService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -1,290 +0,0 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { Query } from 'src/engine/api/rest/types/query.type';
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
import { capitalize } from 'src/utils/capitalize';
import { parseMetadataPath } from 'src/engine/api/rest/rest-api-core-query-builder/utils/path-parsers/parse-metadata-path.utils';
import {
GraphqlApiType,
RestApiService,
} from 'src/engine/api/rest/services/rest-api.service';
@Injectable()
export class RestApiMetadataService {
constructor(
private readonly tokenService: TokenService,
private readonly restApiService: RestApiService,
) {}
fetchMetadataFields(objectNamePlural: string) {
const fields = `
type
name
label
description
icon
isCustom
isActive
isSystem
isNullable
createdAt
updatedAt
fromRelationMetadata {
id
relationType
toObjectMetadata {
id
dataSourceId
nameSingular
namePlural
isSystem
}
toFieldMetadataId
}
toRelationMetadata {
id
relationType
fromObjectMetadata {
id
dataSourceId
nameSingular
namePlural
isSystem
}
fromFieldMetadataId
}
defaultValue
options
`;
switch (objectNamePlural) {
case 'objects':
return `
dataSourceId
nameSingular
namePlural
labelSingular
labelPlural
description
icon
isCustom
isActive
isSystem
createdAt
updatedAt
labelIdentifierFieldMetadataId
imageIdentifierFieldMetadataId
fields(paging: { first: 1000 }) {
edges {
node {
id
${fields}
}
}
}
`;
case 'fields':
return fields;
case 'relations':
return `
relationType
fromObjectMetadata {
id
dataSourceId
nameSingular
namePlural
isSystem
}
fromObjectMetadataId
toObjectMetadata {
id
dataSourceId
nameSingular
namePlural
isSystem
}
toObjectMetadataId
fromFieldMetadataId
toFieldMetadataId
`;
}
}
generateFindManyQuery(objectNameSingular: string, objectNamePlural: string) {
const fields = this.fetchMetadataFields(objectNamePlural);
let filterType = '';
let filterValue = '';
if (objectNamePlural !== 'relations') {
filterType = `($filter: ${objectNameSingular}Filter)`;
filterValue = 'filter: $filter,';
}
return `
query FindMany${capitalize(objectNamePlural)}${filterType} {
${objectNamePlural}(
${filterValue}
paging: { first: 1000 }
) {
edges {
node {
id
${fields}
}
}
}
}
`;
}
generateFindOneQuery(objectNameSingular: string, objectNamePlural: string) {
const fields = this.fetchMetadataFields(objectNamePlural);
return `
query FindOne${capitalize(objectNameSingular)}(
$id: UUID!,
) {
${objectNameSingular}(id: $id) {
id
${fields}
}
}
`;
}
async get(request) {
await this.tokenService.validateToken(request);
const { objectNameSingular, objectNamePlural, id } =
parseMetadataPath(request);
const query = id
? this.generateFindOneQuery(objectNameSingular, objectNamePlural)
: this.generateFindManyQuery(objectNameSingular, objectNamePlural);
const data: Query = {
query,
variables: id ? { id } : request.body,
};
return await this.restApiService.call(
GraphqlApiType.METADATA,
request,
data,
);
}
async create(request) {
await this.tokenService.validateToken(request);
const { objectNameSingular: objectName, objectNamePlural } =
parseMetadataPath(request);
const objectNameCapitalized = capitalize(objectName);
const fields = this.fetchMetadataFields(objectNamePlural);
const query = `
mutation Create${objectNameCapitalized}($input: CreateOne${objectNameCapitalized}Input!) {
createOne${objectNameCapitalized}(input: $input) {
id
${fields}
}
}
`;
const data: Query = {
query,
variables: {
input: {
[objectName]: request.body,
},
},
};
return await this.restApiService.call(
GraphqlApiType.METADATA,
request,
data,
);
}
async update(request) {
await this.tokenService.validateToken(request);
const {
objectNameSingular: objectName,
objectNamePlural,
id,
} = parseMetadataPath(request);
const objectNameCapitalized = capitalize(objectName);
if (!id) {
throw new BadRequestException(
`update ${objectName} query invalid. Id missing. eg: /rest/metadata/${objectName}/0d4389ef-ea9c-4ae8-ada1-1cddc440fb56`,
);
}
const fields = this.fetchMetadataFields(objectNamePlural);
const query = `
mutation Update${objectNameCapitalized}($input: UpdateOne${objectNameCapitalized}Input!) {
updateOne${objectNameCapitalized}(input: $input) {
id
${fields}
}
}
`;
const data: Query = {
query,
variables: {
input: {
update: request.body,
id,
},
},
};
return await this.restApiService.call(
GraphqlApiType.METADATA,
request,
data,
);
}
async delete(request) {
await this.tokenService.validateToken(request);
const { objectNameSingular: objectName, id } = parseMetadataPath(request);
const objectNameCapitalized = capitalize(objectName);
if (!id) {
throw new BadRequestException(
`delete ${objectName} query invalid. Id missing. eg: /rest/metadata/${objectName}/0d4389ef-ea9c-4ae8-ada1-1cddc440fb56`,
);
}
const query = `
mutation Delete${objectNameCapitalized}($input: DeleteOne${objectNameCapitalized}Input!) {
deleteOne${objectNameCapitalized}(input: $input) {
id
}
}
`;
const data: Query = {
query,
variables: {
input: {
id,
},
},
};
return await this.restApiService.call(
GraphqlApiType.METADATA,
request,
data,
);
}
}

View File

@ -1,6 +0,0 @@
import { QueryVariables } from 'src/engine/api/rest/types/query-variables.type';
export type Query = {
query: string;
variables: QueryVariables;
};

View File

@ -133,12 +133,13 @@ export class OpenApiService {
get: { get: {
tags: [item.namePlural], tags: [item.namePlural],
summary: `Find Many ${item.namePlural}`, summary: `Find Many ${item.namePlural}`,
parameters: parameters: [
item.namePlural !== 'relations' { $ref: '#/components/parameters/limit' },
? [{ $ref: '#/components/parameters/filter' }] { $ref: '#/components/parameters/startingAfter' },
: undefined, { $ref: '#/components/parameters/endingBefore' },
],
responses: { responses: {
'200': getFindManyResponse200(item), '200': getFindManyResponse200(item, true),
'400': { $ref: '#/components/responses/400' }, '400': { $ref: '#/components/responses/400' },
'401': { $ref: '#/components/responses/401' }, '401': { $ref: '#/components/responses/401' },
}, },
@ -161,7 +162,7 @@ export class OpenApiService {
summary: `Find One ${item.nameSingular}`, summary: `Find One ${item.nameSingular}`,
parameters: [{ $ref: '#/components/parameters/idPath' }], parameters: [{ $ref: '#/components/parameters/idPath' }],
responses: { responses: {
'200': getFindOneResponse200(item), '200': getFindOneResponse200(item, true),
'400': { $ref: '#/components/responses/400' }, '400': { $ref: '#/components/responses/400' },
'401': { $ref: '#/components/responses/401' }, '401': { $ref: '#/components/responses/401' },
}, },
@ -177,18 +178,20 @@ export class OpenApiService {
'401': { $ref: '#/components/responses/401' }, '401': { $ref: '#/components/responses/401' },
}, },
}, },
patch: { ...(item.nameSingular !== 'relation' && {
tags: [item.namePlural], patch: {
summary: `Update One ${item.namePlural}`, tags: [item.namePlural],
operationId: `updateOne${capitalize(item.nameSingular)}`, summary: `Update One ${item.nameSingular}`,
parameters: [{ $ref: '#/components/parameters/idPath' }], operationId: `updateOne${capitalize(item.nameSingular)}`,
requestBody: getRequestBody(capitalize(item.nameSingular)), parameters: [{ $ref: '#/components/parameters/idPath' }],
responses: { requestBody: getRequestBody(capitalize(item.nameSingular)),
'200': getUpdateOneResponse200(item, true), responses: {
'400': { $ref: '#/components/responses/400' }, '200': getUpdateOneResponse200(item, true),
'401': { $ref: '#/components/responses/401' }, '400': { $ref: '#/components/responses/400' },
'401': { $ref: '#/components/responses/401' },
},
}, },
}, }),
} as OpenAPIV3_1.PathItemObject; } as OpenAPIV3_1.PathItemObject;
return path; return path;
@ -197,7 +200,7 @@ export class OpenApiService {
schema.components = { schema.components = {
...schema.components, // components.securitySchemes is defined in base Schema ...schema.components, // components.securitySchemes is defined in base Schema
schemas: computeMetadataSchemaComponents(metadata), schemas: computeMetadataSchemaComponents(metadata),
parameters: computeParameterComponents(), parameters: computeParameterComponents(true),
responses: { responses: {
'400': get400ErrorResponses(), '400': get400ErrorResponses(),
'401': get401ErrorResponses(), '401': get401ErrorResponses(),

View File

@ -9,10 +9,10 @@ import {
computeOrderByParameters, computeOrderByParameters,
computeStartingAfterParameters, computeStartingAfterParameters,
} from 'src/engine/core-modules/open-api/utils/parameters.utils'; } from 'src/engine/core-modules/open-api/utils/parameters.utils';
import { DEFAULT_ORDER_DIRECTION } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/order-by-input.factory'; import { DEFAULT_ORDER_DIRECTION } from 'src/engine/api/rest/input-factories/order-by-input.factory';
import { FilterComparators } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/parse-base-filter.utils'; import { FilterComparators } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/parse-base-filter.utils';
import { Conjunctions } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/parse-filter.utils'; import { Conjunctions } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/parse-filter.utils';
import { DEFAULT_CONJUNCTION } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/add-default-conjunction.utils'; import { DEFAULT_CONJUNCTION } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/add-default-conjunction.utils';
describe('computeParameters', () => { describe('computeParameters', () => {
describe('computeLimit', () => { describe('computeLimit', () => {

View File

@ -218,10 +218,9 @@ export const computeSchemaComponents = (
); );
}; };
export const computeParameterComponents = (): Record< export const computeParameterComponents = (
string, fromMetadata = false,
OpenAPIV3_1.ParameterObject ): Record<string, OpenAPIV3_1.ParameterObject> => {
> => {
return { return {
idPath: computeIdPathParameter(), idPath: computeIdPathParameter(),
startingAfter: computeStartingAfterParameters(), startingAfter: computeStartingAfterParameters(),
@ -229,7 +228,7 @@ export const computeParameterComponents = (): Record<
filter: computeFilterParameters(), filter: computeFilterParameters(),
depth: computeDepthParameters(), depth: computeDepthParameters(),
orderBy: computeOrderByParameters(), orderBy: computeOrderByParameters(),
limit: computeLimitParameters(), limit: computeLimitParameters(fromMetadata),
}; };
}; };
@ -240,7 +239,7 @@ export const computeMetadataSchemaComponents = (
(schemas, item) => { (schemas, item) => {
switch (item.nameSingular) { switch (item.nameSingular) {
case 'object': { case 'object': {
schemas[`${capitalize(item.nameSingular)} with Relations`] = { schemas[`${capitalize(item.nameSingular)}`] = {
type: 'object', type: 'object',
description: `An object`, description: `An object`,
properties: { properties: {
@ -290,7 +289,7 @@ export const computeMetadataSchemaComponents = (
return schemas; return schemas;
} }
case 'field': { case 'field': {
schemas[`${capitalize(item.nameSingular)} with Relations`] = { schemas[`${capitalize(item.nameSingular)}`] = {
type: 'object', type: 'object',
description: `A field`, description: `A field`,
properties: { properties: {
@ -358,7 +357,7 @@ export const computeMetadataSchemaComponents = (
return schemas; return schemas;
} }
case 'relation': { case 'relation': {
schemas[`${capitalize(item.nameSingular)} with Relations`] = { schemas[`${capitalize(item.nameSingular)}`] = {
type: 'object', type: 'object',
description: 'A relation', description: 'A relation',
properties: { properties: {

View File

@ -2,12 +2,14 @@ import { OpenAPIV3_1 } from 'openapi-types';
import { OrderByDirection } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; import { OrderByDirection } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface';
import { FilterComparators } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/parse-base-filter.utils'; import { FilterComparators } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/parse-base-filter.utils';
import { Conjunctions } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/parse-filter.utils'; import { Conjunctions } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/parse-filter.utils';
import { DEFAULT_ORDER_DIRECTION } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/order-by-input.factory'; import { DEFAULT_ORDER_DIRECTION } from 'src/engine/api/rest/input-factories/order-by-input.factory';
import { DEFAULT_CONJUNCTION } from 'src/engine/api/rest/rest-api-core-query-builder/factories/input-factories/filter-utils/add-default-conjunction.utils'; import { DEFAULT_CONJUNCTION } from 'src/engine/api/rest/core/query-builder/utils/filter-utils/add-default-conjunction.utils';
export const computeLimitParameters = (): OpenAPIV3_1.ParameterObject => { export const computeLimitParameters = (
fromMetadata = false,
): OpenAPIV3_1.ParameterObject => {
return { return {
name: 'limit', name: 'limit',
in: 'query', in: 'query',
@ -16,8 +18,8 @@ export const computeLimitParameters = (): OpenAPIV3_1.ParameterObject => {
schema: { schema: {
type: 'integer', type: 'integer',
minimum: 0, minimum: 0,
maximum: 60, maximum: fromMetadata ? 1000 : 60,
default: 60, default: fromMetadata ? 1000 : 60,
}, },
}; };
}; };

View File

@ -105,7 +105,7 @@ export const computeSingleResultPath = (
}, },
patch: { patch: {
tags: [item.namePlural], tags: [item.namePlural],
summary: `Update One ${item.namePlural}`, summary: `Update One ${item.nameSingular}`,
operationId: `UpdateOne${capitalize(item.nameSingular)}`, operationId: `UpdateOne${capitalize(item.nameSingular)}`,
parameters: [ parameters: [
{ $ref: '#/components/parameters/idPath' }, { $ref: '#/components/parameters/idPath' },

View File

@ -3,6 +3,7 @@ import { capitalize } from 'src/utils/capitalize';
export const getFindManyResponse200 = ( export const getFindManyResponse200 = (
item: Pick<ObjectMetadataEntity, 'nameSingular' | 'namePlural'>, item: Pick<ObjectMetadataEntity, 'nameSingular' | 'namePlural'>,
fromMetadata = false,
) => { ) => {
return { return {
description: 'Successful operation', description: 'Successful operation',
@ -19,7 +20,7 @@ export const getFindManyResponse200 = (
items: { items: {
$ref: `#/components/schemas/${capitalize( $ref: `#/components/schemas/${capitalize(
item.nameSingular, item.nameSingular,
)} with Relations`, )}${!fromMetadata ? ' with Relations' : ''}`,
}, },
}, },
}, },
@ -32,9 +33,11 @@ export const getFindManyResponse200 = (
endCursor: { type: 'string' }, endCursor: { type: 'string' },
}, },
}, },
totalCount: { ...(!fromMetadata && {
type: 'integer', totalCount: {
}, type: 'integer',
},
}),
}, },
example: { example: {
data: { data: {
@ -59,6 +62,7 @@ export const getFindManyResponse200 = (
export const getFindOneResponse200 = ( export const getFindOneResponse200 = (
item: Pick<ObjectMetadataEntity, 'nameSingular'>, item: Pick<ObjectMetadataEntity, 'nameSingular'>,
fromMetadata = false,
) => { ) => {
return { return {
description: 'Successful operation', description: 'Successful operation',
@ -71,9 +75,9 @@ export const getFindOneResponse200 = (
type: 'object', type: 'object',
properties: { properties: {
[item.nameSingular]: { [item.nameSingular]: {
$ref: `#/components/schemas/${capitalize( $ref: `#/components/schemas/${capitalize(item.nameSingular)}${
item.nameSingular, !fromMetadata ? ' with Relations' : ''
)} with Relations`, }`,
}, },
}, },
}, },