From 1bc3365ab8e38298e82cd82b58d9e05f691b63d9 Mon Sep 17 00:00:00 2001 From: Roman Kalyakin Date: Wed, 13 Nov 2024 22:29:15 +0100 Subject: [PATCH] refactor public base find response --- src/models/generated/schemasPublic.d.ts | 19 +++++++++++ src/schema/schemasPublic/BaseFind.json | 32 +++++++++++++++++++ src/services/collections/collections.hooks.js | 6 +++- .../collections/collections.schema.ts | 5 +++ src/services/entities/entities.hooks.ts | 6 +++- src/services/entities/entities.schema.ts | 2 ++ src/services/newspapers/newspapers.hooks.js | 6 +++- src/services/newspapers/newspapers.schema.ts | 2 ++ .../search-facets/search-facets.schema.ts | 1 + src/services/search/search.hooks.js | 4 ++- src/services/search/search.schema.ts | 1 + .../text-reuse-clusters.hooks.js | 2 ++ .../text-reuse-clusters.schema.ts | 2 ++ .../text-reuse-passages.hooks.js | 2 ++ .../text-reuse-passages.schema.ts | 2 ++ src/transformers/base.ts | 13 ++++++++ src/transformers/searchFacet.ts | 16 ++++------ src/util/openapi.ts | 11 +++++-- 18 files changed, 116 insertions(+), 16 deletions(-) create mode 100644 src/schema/schemasPublic/BaseFind.json create mode 100644 src/transformers/base.ts diff --git a/src/models/generated/schemasPublic.d.ts b/src/models/generated/schemasPublic.d.ts index 4d1f93b7..7b62308a 100644 --- a/src/models/generated/schemasPublic.d.ts +++ b/src/models/generated/schemasPublic.d.ts @@ -7,6 +7,25 @@ */ +export interface BaseFindResponse { + data: unknown[]; + pagination: { + /** + * The total number of items matching the query + */ + total: number; + /** + * The number of items returned in this response + */ + limit: number; + /** + * Starting index of the items subset returned in this response + */ + offset: number; + }; +} + + /** * Collection details. */ diff --git a/src/schema/schemasPublic/BaseFind.json b/src/schema/schemasPublic/BaseFind.json new file mode 100644 index 00000000..8c20eea8 --- /dev/null +++ b/src/schema/schemasPublic/BaseFind.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "title": "Base Find Response", + "properties": { + "data": { + "type": "array", + "items": {} + }, + "pagination": { + "type": "object", + "additionalProperties": false, + "properties": { + "total": { + "type": "integer", + "description": "The total number of items matching the query" + }, + "limit": { + "type": "integer", + "description": "The number of items returned in this response" + }, + "offset": { + "type": "integer", + "description": "Starting index of the items subset returned in this response" + } + }, + "required": ["total", "limit", "offset"] + } + }, + "required": ["data", "pagination"], + "additionalProperties": false +} diff --git a/src/services/collections/collections.hooks.js b/src/services/collections/collections.hooks.js index 0e8d7f90..3eb31d96 100644 --- a/src/services/collections/collections.hooks.js +++ b/src/services/collections/collections.hooks.js @@ -3,6 +3,7 @@ import { rateLimit } from '../../hooks/rateLimiter' import { transformResponseDataItem, transformResponse, renameQueryParameters } from '../../hooks/transformation' import { inPublicApi } from '../../hooks/redaction' import { transformCollection } from '../../transformers/collection' +import { transformBaseFind } from '../../transformers/base' const { queryWithCommonParams, validate, utils, REGEX_UIDS } = require('../../hooks/params') @@ -94,7 +95,10 @@ module.exports = { after: { all: [], - find: [transformResponseDataItem(transformCollection, inPublicApi)], + find: [ + transformResponse(transformBaseFind, inPublicApi), + transformResponseDataItem(transformCollection, inPublicApi), + ], get: [transformResponse(transformCollection, inPublicApi)], create: [transformResponse(transformCollection, inPublicApi)], update: [], diff --git a/src/services/collections/collections.schema.ts b/src/services/collections/collections.schema.ts index 6d635681..dc2d4108 100644 --- a/src/services/collections/collections.schema.ts +++ b/src/services/collections/collections.schema.ts @@ -72,6 +72,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'find', schema: 'Collection', + isPublic: isPublicApi, }), }, get: { @@ -91,6 +92,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'get', schema: 'Collection', + isPublic: isPublicApi, }), }, create: { @@ -102,6 +104,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'create', schema: 'Collection', + isPublic: isPublicApi, }), }, patch: { @@ -124,6 +127,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'patch', schema: 'Collection', + isPublic: isPublicApi, }), }, remove: { @@ -143,6 +147,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'remove', schema: 'CollectionsRemoveResponse', + isPublic: isPublicApi, }), }, }, diff --git a/src/services/entities/entities.hooks.ts b/src/services/entities/entities.hooks.ts index c724f0db..1623a70b 100644 --- a/src/services/entities/entities.hooks.ts +++ b/src/services/entities/entities.hooks.ts @@ -7,6 +7,7 @@ const { qToSolrFilter, filtersToSolrQuery } = require('../../hooks/search') import { transformResponseDataItem, transformResponse, renameQueryParameters } from '../../hooks/transformation' import { inPublicApi } from '../../hooks/redaction' import { transformEntityDetails } from '../../transformers/entity' +import { transformBaseFind } from '../../transformers/base' const orderByMap = { relevance: 'score ASC', @@ -96,7 +97,10 @@ export default { after: { all: [], - find: [transformResponseDataItem(transformEntityDetails, inPublicApi)], + find: [ + transformResponse(transformBaseFind, inPublicApi), + transformResponseDataItem(transformEntityDetails, inPublicApi), + ], get: [transformResponse(transformEntityDetails, inPublicApi)], create: [], update: [], diff --git a/src/services/entities/entities.schema.ts b/src/services/entities/entities.schema.ts index 5cc231a5..5fe14c2e 100644 --- a/src/services/entities/entities.schema.ts +++ b/src/services/entities/entities.schema.ts @@ -74,6 +74,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'find', schema: 'EntityDetails', + isPublic: isPublicApi, }), }, get: { @@ -93,6 +94,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'get', schema: 'EntityDetails', + isPublic: isPublicApi, }), }, }, diff --git a/src/services/newspapers/newspapers.hooks.js b/src/services/newspapers/newspapers.hooks.js index 6b35257f..076efe4e 100644 --- a/src/services/newspapers/newspapers.hooks.js +++ b/src/services/newspapers/newspapers.hooks.js @@ -4,6 +4,7 @@ import { OrderByChoices } from './newspapers.schema' import { transformResponseDataItem, transformResponse, renameQueryParameters } from '../../hooks/transformation' import { inPublicApi } from '../../hooks/redaction' import { transformNewspaper } from '../../transformers/newspaper' +import { transformBaseFind } from '../../transformers/base' const { queryWithCommonParams, validate, utils } = require('../../hooks/params') const { checkCachedContents, returnCachedContents, saveResultsInCache } = require('../../hooks/redis') @@ -74,7 +75,10 @@ module.exports = { after: { all: [returnCachedContents(), saveResultsInCache()], - find: [transformResponseDataItem(transformNewspaper, inPublicApi)], + find: [ + transformResponse(transformBaseFind, inPublicApi), + transformResponseDataItem(transformNewspaper, inPublicApi), + ], get: [transformResponse(transformNewspaper, inPublicApi)], create: [], update: [], diff --git a/src/services/newspapers/newspapers.schema.ts b/src/services/newspapers/newspapers.schema.ts index d7f8bd6e..57f85631 100644 --- a/src/services/newspapers/newspapers.schema.ts +++ b/src/services/newspapers/newspapers.schema.ts @@ -95,6 +95,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'find', schema: 'Newspaper', + isPublic: isPublicApi, }), }, get: { @@ -114,6 +115,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'get', schema: 'Newspaper', + isPublic: isPublicApi, }), }, }, diff --git a/src/services/search-facets/search-facets.schema.ts b/src/services/search-facets/search-facets.schema.ts index 6e34503a..b584456a 100644 --- a/src/services/search-facets/search-facets.schema.ts +++ b/src/services/search-facets/search-facets.schema.ts @@ -167,6 +167,7 @@ export const getDocs = (index: IndexId, isPublicApi: boolean): ServiceSwaggerOpt responses: getStandardResponses({ method: 'find', schema: 'SearchFacetBucket', + isPublic: isPublicApi, }), }, }, diff --git a/src/services/search/search.hooks.js b/src/services/search/search.hooks.js index 63e8c207..84c420fb 100644 --- a/src/services/search/search.hooks.js +++ b/src/services/search/search.hooks.js @@ -1,7 +1,8 @@ import { authenticateAround as authenticate } from '../../hooks/authenticate' import { rateLimit } from '../../hooks/rateLimiter' import { redactResponseDataItem, defaultCondition, inPublicApi } from '../../hooks/redaction' -import { transformResponseDataItem, renameQueryParameters } from '../../hooks/transformation' +import { transformResponseDataItem, transformResponse, renameQueryParameters } from '../../hooks/transformation' +import { transformBaseFind } from '../../transformers/base' import { transformContentItem } from '../../transformers/contentItem' import { loadYamlFile } from '../../util/yaml' @@ -106,6 +107,7 @@ module.exports = { all: [], find: [ displayQueryParams(['queryComponents', 'filters']), + transformResponse(transformBaseFind, inPublicApi), resolveQueryComponents(), protect('content'), transformResponseDataItem(transformContentItem, inPublicApi), diff --git a/src/services/search/search.schema.ts b/src/services/search/search.schema.ts index 41d85cd4..37d1490d 100644 --- a/src/services/search/search.schema.ts +++ b/src/services/search/search.schema.ts @@ -89,6 +89,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'find', schema: 'ContentItem', + isPublic: isPublicApi, }), }, }, diff --git a/src/services/text-reuse-clusters/text-reuse-clusters.hooks.js b/src/services/text-reuse-clusters/text-reuse-clusters.hooks.js index ef46af2e..6787636d 100644 --- a/src/services/text-reuse-clusters/text-reuse-clusters.hooks.js +++ b/src/services/text-reuse-clusters/text-reuse-clusters.hooks.js @@ -12,6 +12,7 @@ import { renameQueryParameters, } from '../../hooks/transformation' import { transformTextReuseCluster } from '../../transformers/textReuse' +import { transformBaseFind } from '../../transformers/base' // const { validateWithSchema } = require('../../hooks/schema') @@ -52,6 +53,7 @@ module.exports = { ], find: [ renameTopLevelField(['clusters', 'data'], inPublicApi), + transformResponse(transformBaseFind, inPublicApi), transformResponseDataItem(transformTextReuseCluster, inPublicApi), redactResponseDataItem(trPassageRedactionPolicy, defaultCondition), ], diff --git a/src/services/text-reuse-clusters/text-reuse-clusters.schema.ts b/src/services/text-reuse-clusters/text-reuse-clusters.schema.ts index 23ee51ec..d55a8380 100644 --- a/src/services/text-reuse-clusters/text-reuse-clusters.schema.ts +++ b/src/services/text-reuse-clusters/text-reuse-clusters.schema.ts @@ -89,6 +89,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'find', schema: 'TextReuseCluster', + isPublic: isPublicApi, }), }, get: { @@ -98,6 +99,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'get', schema: 'TextReuseCluster', + isPublic: isPublicApi, }), }, }, diff --git a/src/services/text-reuse-passages/text-reuse-passages.hooks.js b/src/services/text-reuse-passages/text-reuse-passages.hooks.js index 58cd6773..e2c5a0fc 100644 --- a/src/services/text-reuse-passages/text-reuse-passages.hooks.js +++ b/src/services/text-reuse-passages/text-reuse-passages.hooks.js @@ -7,6 +7,7 @@ import { redactResponse, redactResponseDataItem, defaultCondition, inPublicApi } import { loadYamlFile } from '../../util/yaml' import { transformResponseDataItem, transformResponse } from '../../hooks/transformation' import { transformTextReusePassage } from '../../transformers/textReuse' +import { transformBaseFind } from '../../transformers/base' const trPassageRedactionPolicy = loadYamlFile(`${__dirname}/resources/trPassageRedactionPolicy.yml`) @@ -39,6 +40,7 @@ module.exports = { redactResponse(trPassageRedactionPolicy, defaultCondition), ], find: [ + transformResponse(transformBaseFind, inPublicApi), transformResponseDataItem(transformTextReusePassage, inPublicApi), redactResponseDataItem(trPassageRedactionPolicy, defaultCondition), ], diff --git a/src/services/text-reuse-passages/text-reuse-passages.schema.ts b/src/services/text-reuse-passages/text-reuse-passages.schema.ts index 93d64034..2fe30f9f 100644 --- a/src/services/text-reuse-passages/text-reuse-passages.schema.ts +++ b/src/services/text-reuse-passages/text-reuse-passages.schema.ts @@ -66,6 +66,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'find', schema: 'TextReusePassage', + isPublic: isPublicApi, }), }, get: { @@ -75,6 +76,7 @@ export const getDocs = (isPublicApi: boolean): ServiceSwaggerOptions => ({ responses: getStandardResponses({ method: 'get', schema: 'TextReusePassage', + isPublic: isPublicApi, }), }, }, diff --git a/src/transformers/base.ts b/src/transformers/base.ts new file mode 100644 index 00000000..cecf2f74 --- /dev/null +++ b/src/transformers/base.ts @@ -0,0 +1,13 @@ +import { BaseFind } from '../models/generated/schemas' +import { BaseFindResponse as BaseFindPublic } from '../models/generated/schemasPublic' + +export const transformBaseFind = (input: BaseFind): BaseFindPublic => { + return { + pagination: { + total: input.total, + limit: input.limit, + offset: input.offset, + }, + data: input.data, + } +} diff --git a/src/transformers/searchFacet.ts b/src/transformers/searchFacet.ts index 94838a1e..ecd050ba 100644 --- a/src/transformers/searchFacet.ts +++ b/src/transformers/searchFacet.ts @@ -3,17 +3,16 @@ import { ImpressoApplication } from '../types' import { SearchFacet, - BaseFind, SearchFacetBucket as SearchFacetBucketInternal, SearchFacetRangeBucket, } from '../models/generated/schemas' -import { SearchFacetBucket } from '../models/generated/schemasPublic' +import { SearchFacetBucket, BaseFindResponse } from '../models/generated/schemasPublic' import Collection from '../models/collections.model' import Newspaper from '../models/newspapers.model' import Entity from '../models/entities.model' import Topic from '../models/topics.model' -interface FacetContainer extends BaseFind { +interface FacetContainer extends BaseFindResponse { data: SearchFacetBucket[] } @@ -77,13 +76,12 @@ const transformBucket = ( } export const transformSearchFacet = (input: SearchFacet, context: HookContext): FacetContainer => { - console.log('III', input, context.id) - return { + pagination: { + total: input.numBuckets, + limit: context.params?.query?.limit ?? input.buckets.length, + offset: context.params?.query?.offset ?? 0, + }, data: input.buckets.map(b => transformBucket(b, context.id as string)), - total: input.numBuckets, - limit: context.params?.query?.limit ?? input.buckets.length, - offset: context.params?.query?.offset ?? 0, - info: {}, } } diff --git a/src/util/openapi.ts b/src/util/openapi.ts index 7a74722b..a0cb0995 100644 --- a/src/util/openapi.ts +++ b/src/util/openapi.ts @@ -55,13 +55,17 @@ interface GetStandardResponsesParams { authEnabled?: boolean isRateLimited?: boolean standardPagination?: boolean + isPublic?: boolean } const baseFindResponse = require('../schema/schemas/BaseFind.json') delete baseFindResponse['$schema'] -const getBaseFindResponse = (itemRef: string): JSONSchema => { - const response = JSON.parse(JSON.stringify(baseFindResponse)) +const baseFindResponsePublic = require('../schema/schemasPublic/BaseFind.json') +delete baseFindResponsePublic['$schema'] + +const getBaseFindResponse = (itemRef: string, isPublic: boolean): JSONSchema => { + const response = JSON.parse(JSON.stringify(isPublic ? baseFindResponsePublic : baseFindResponse)) response['properties']['data']['items'] = { $ref: itemRef, } @@ -84,6 +88,7 @@ export const getStandardResponses = ({ authEnabled = true, isRateLimited = true, standardPagination = true, + isPublic = false, }: GetStandardResponsesParams) => { const defaultResponses: Record = { 422: { @@ -107,7 +112,7 @@ export const getStandardResponses = ({ if (method === 'find' && standardPagination) { defaultResponses[200] = { description: 'Success', - content: asApplicationJson(getBaseFindResponse(`#/components/schemas/${schema}`)), + content: asApplicationJson(getBaseFindResponse(`#/components/schemas/${schema}`, isPublic)), headers: { ...defaultHeaders }, } } else {