diff --git a/ai-service/package.json b/ai-service/package.json index bec194a560..7ddb648b83 100644 --- a/ai-service/package.json +++ b/ai-service/package.json @@ -1,11 +1,11 @@ { "name": "ai-service", - "version": "2.27.0", + "version": "2.27.1", "main": "dist/app.js", "license": "Apache-2.0", "dependencies": { - "@guardian/common": "^2.27.0", - "@guardian/interfaces": "^2.27.0", + "@guardian/common": "^2.27.1", + "@guardian/interfaces": "^2.27.1", "@mikro-orm/core": "6.2.2", "@mikro-orm/mongodb": "6.2.2", "@nestjs/common": "^9.4.1", diff --git a/analytics-service/package.json b/analytics-service/package.json index 0981d383bc..419737f981 100644 --- a/analytics-service/package.json +++ b/analytics-service/package.json @@ -13,8 +13,8 @@ }, "author": "Envision Blockchain Solutions ", "dependencies": { - "@guardian/common": "^2.27.0", - "@guardian/interfaces": "^2.27.0", + "@guardian/common": "^2.27.1", + "@guardian/interfaces": "^2.27.1", "@nestjs/common": "^9.4.1", "@nestjs/core": "^9.4.1", "@nestjs/jwt": "^10.0.3", @@ -82,5 +82,5 @@ "test": "mocha tests/**/*.test.js --reporter mocha-junit-reporter --reporter-options mochaFile=../test_results/ui-service.xml" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/api-gateway/package.json b/api-gateway/package.json index bf7f514eab..de2bfbb9df 100644 --- a/api-gateway/package.json +++ b/api-gateway/package.json @@ -4,8 +4,8 @@ "@fastify/formbody": "^7.4.0", "@fastify/multipart": "^8.2.0", "@fastify/static": "^7.0.0", - "@guardian/common": "^2.27.0", - "@guardian/interfaces": "^2.27.0", + "@guardian/common": "^2.27.1", + "@guardian/interfaces": "^2.27.1", "@nestjs/common": "^9.4.1", "@nestjs/core": "^9.4.1", "@nestjs/jwt": "^10.0.3", @@ -88,5 +88,5 @@ "test": "mocha tests/**/*.test.js --reporter mocha-junit-reporter --reporter-options mochaFile=../test_results/ui-service.xml" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/api-tests/package.json b/api-tests/package.json index cc6ec94205..528c8c7f0d 100644 --- a/api-tests/package.json +++ b/api-tests/package.json @@ -1,6 +1,6 @@ { "name": "api-tests", - "version": "2.27.0", + "version": "2.27.1", "description": "API Tests", "main": "index.js", "type": "module", diff --git a/auth-service/package.json b/auth-service/package.json index c1bbae79b4..8a43b27d51 100644 --- a/auth-service/package.json +++ b/auth-service/package.json @@ -10,8 +10,8 @@ "image-size": "1.0.2" }, "dependencies": { - "@guardian/common": "^2.27.0", - "@guardian/interfaces": "^2.27.0", + "@guardian/common": "^2.27.1", + "@guardian/interfaces": "^2.27.1", "@meeco/cryppo": "^2.0.2", "@mikro-orm/core": "6.2.2", "@mikro-orm/mongodb": "6.2.2", @@ -79,5 +79,5 @@ "test": "mocha tests/**/*.test.js --reporter mocha-junit-reporter --reporter-options mochaFile=../test_results/ui-service.xml" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/common/package.json b/common/package.json index 750e854b50..41d014647d 100644 --- a/common/package.json +++ b/common/package.json @@ -5,7 +5,7 @@ "@azure/identity": "^3.2.2", "@azure/keyvault-secrets": "^4.7.0", "@google-cloud/secret-manager": "^4.2.2", - "@guardian/interfaces": "^2.27.0", + "@guardian/interfaces": "^2.27.1", "@hashgraph/sdk": "2.46.0", "@mattrglobal/jsonld-signatures-bbs": "^1.1.2", "@meeco/cryppo": "^2.0.2", @@ -87,5 +87,5 @@ "test:stability": "mocha tests/stability.test.js" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/configs/nats.conf b/configs/nats.conf new file mode 100644 index 0000000000..9366d607d9 --- /dev/null +++ b/configs/nats.conf @@ -0,0 +1,29 @@ +# Client port of 4222 on all interfaces +port: 4222 + +# HTTP monitoring port +monitor_port: 8222 + +# This is for clustering multiple servers together. +cluster { + # It is recommended to set a cluster name + name: "my_cluster" + + # Route connections to be received on any interface on port 6222 + port: 6222 + + # Routes are protected, so need to use them with --routes flag + # e.g. --routes=nats-route://ruser:T0pS3cr3t@otherdockerhost:6222 + authorization { + user: ruser + password: T0pS3cr3t + timeout: 2 + } + + # Routes are actively solicited and connected to from this server. + # This Docker image has none by default, but you can pass a + # flag to the nats-server docker image to create one to an existing server. + routes = [] +} + +max_payload: 64MB diff --git a/docker-compose-indexer.yml b/docker-compose-indexer.yml index 9bc135cfa8..bfde6bfeb5 100644 --- a/docker-compose-indexer.yml +++ b/docker-compose-indexer.yml @@ -1,7 +1,6 @@ -version: "3.8" services: mongo: - image: mongo:6.0.13 + image: mongo:6.0.16 command: "--setParameter allowDiskUseByDefault=true" restart: always expose: @@ -19,15 +18,17 @@ services: - mongo ipfs-node: - image: ipfs/kubo:latest + image: ipfs/kubo:v0.29.0 message-broker: - image: nats:2.9.24 + image: nats:2.9.25 expose: - 4222 ports: - '8222:8222' - command: '--http_port 8222' + command: '-c /etc/nats/nats.conf --http_port 8222' + volumes: + - ./configs/nats.conf:/etc/nats/nats.conf indexer-worker-service: env_file: @@ -39,15 +40,16 @@ services: depends_on: - mongo - message-broker + - indexer-service environment: - GUARDIAN_ENV=${GUARDIAN_ENV} expose: - 6555 volumes: - - ./indexer-worker-service/tls:/usr/local/indexer-worker-service/tls:ro - - ./indexer-worker-service/configs:/usr/local/indexer-worker-service/configs:ro + - ./indexer-worker-service/tls:/usr/local/app/tls:ro + - ./indexer-worker-service/configs:/usr/local/app/configs:ro deploy: - replicas: 5 + replicas: 3 indexer-api-gateway: env_file: @@ -66,7 +68,7 @@ services: environment: - GUARDIAN_ENV=${GUARDIAN_ENV} volumes: - - ./indexer-api-gateway/configs:/usr/local/indexer-api-gateway/configs:ro + - ./indexer-api-gateway/configs:/usr/local/app/configs:ro indexer-service: env_file: @@ -76,8 +78,8 @@ services: dockerfile: ./indexer-service/Dockerfile init: true volumes: - - ./indexer-service/tls:/usr/local/indexer-service/tls:ro - - ./indexer-service/configs:/usr/local/indexer-service/configs:ro + - ./indexer-service/tls:/usr/local/app/tls:ro + - ./indexer-service/configs:/usr/local/app/configs:ro depends_on: - mongo - message-broker diff --git a/docker-compose-production.yml b/docker-compose-production.yml index 985be4f569..f0a0bd65ce 100644 --- a/docker-compose-production.yml +++ b/docker-compose-production.yml @@ -33,7 +33,9 @@ services: - 4222 ports: - '8222:8222' - command: '--http_port 8222' + command: '-c /etc/nats/nats.conf --http_port 8222' + volumes: + - ./configs/nats.conf:/etc/nats/nats.conf vault: image: hashicorp/vault:1.12.11 diff --git a/docker-compose.yml b/docker-compose.yml index b85fda4c77..4b7e0ab212 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -54,7 +54,9 @@ services: - 4222 ports: - '8222:8222' - command: '--http_port 8222' + command: '-c /etc/nats/nats.conf --http_port 8222' + volumes: + - ./configs/nats.conf:/etc/nats/nats.conf vault: image: hashicorp/vault:1.12.11 diff --git a/frontend/package.json b/frontend/package.json index cab30c362b..9b938d5934 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -74,5 +74,5 @@ "test": "ng test", "watch": "ng build --watch --configuration development --output-path ../www-data" }, - "version": "2.27.0" + "version": "2.27.1" } diff --git a/guardian-service/package.json b/guardian-service/package.json index ecc5fd9642..ca9e851a29 100644 --- a/guardian-service/package.json +++ b/guardian-service/package.json @@ -16,8 +16,8 @@ "image-size": "1.0.2" }, "dependencies": { - "@guardian/common": "^2.27.0", - "@guardian/interfaces": "^2.27.0", + "@guardian/common": "^2.27.1", + "@guardian/interfaces": "^2.27.1", "@hashgraph/sdk": "2.46.0", "@mattrglobal/jsonld-signatures-bbs": "^1.1.2", "@meeco/cryppo": "^2.0.2", @@ -99,5 +99,5 @@ "test:stability": "mocha tests/stability.test.mjs" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/indexer-api-gateway/Dockerfile b/indexer-api-gateway/Dockerfile index b0bf0edc32..f9f609d814 100644 --- a/indexer-api-gateway/Dockerfile +++ b/indexer-api-gateway/Dockerfile @@ -1,55 +1,57 @@ -FROM node:20 AS interfacesModuleBuilder -WORKDIR /usr/local/indexer-interfaces -COPY ./indexer-interfaces/package.json ./ -COPY ./indexer-interfaces/tsconfig*.json ./ -COPY ./yarn.lock ./ -COPY ./package-lock.json ./ -ADD ./indexer-interfaces/src ./src/. -RUN yarn install -RUN yarn pack - -FROM node:20 AS commonModuleBuilder -WORKDIR /usr/local/indexer-common -COPY --from=interfacesModuleBuilder /usr/local/indexer-interfaces/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz -COPY ./indexer-common/package.json ./ -COPY ./indexer-common/tsconfig*.json ./ -COPY ./yarn.lock ./ -COPY ./package-lock.json ./ -RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/interfaces']='file:/tmp/indexer-interfaces.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN yarn install -ADD ./indexer-common/src ./src/. -RUN yarn pack - -FROM node:20 AS apiGatewayBuilder -WORKDIR /usr/local/indexer-api-gateway -COPY --from=interfacesModuleBuilder /usr/local/indexer-interfaces/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz -COPY --from=commonModuleBuilder /usr/local/indexer-common/indexer-common-*.tgz /tmp/indexer-common.tgz -COPY ./indexer-api-gateway/package.json ./ -COPY ./indexer-api-gateway/tsconfig*.json ./ -COPY ./indexer-api-gateway/Gulpfile.mjs ./ -COPY ./yarn.lock ./ -COPY ./package-lock.json ./ -RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/interfaces']='file:/tmp/indexer-interfaces.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/common']='file:/tmp/indexer-common.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN yarn install -ADD ./indexer-api-gateway/environments ./environments/. -ADD ./indexer-api-gateway/src ./src/. -RUN yarn run build:prod - -FROM node:20 -ENV PLATFORM="docker" -ENV NODE_ENV="production" -WORKDIR /usr/local/indexer-api-gateway -COPY --from=interfacesModuleBuilder /usr/local/indexer-interfaces/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz -COPY --from=commonModuleBuilder /usr/local/indexer-common/indexer-common-*.tgz /tmp/indexer-common.tgz -COPY --from=apiGatewayBuilder /usr/local/indexer-api-gateway/yarn.lock ./ -COPY ./indexer-api-gateway/package.json ./ -COPY ./yarn.lock ./ -COPY ./package-lock.json ./ +# syntax=docker/dockerfile:1 +# Stage 0: Use node image for base image for all stages +ARG NODE_VERSION=20.16-alpine +FROM node:${NODE_VERSION} as base +WORKDIR /usr/local/app +# Define an argument `YARN_CACHE_FOLDER` for the Yarn cache directory +ARG YARN_CACHE_FOLDER=/root/.yarn + +# Stage 1: Build interfaces module +FROM base as interfaces +COPY --link indexer-interfaces/package.json indexer-interfaces/tsconfig*.json yarn.lock ./ +COPY --link indexer-interfaces/src src/ +# Here and after. Leverage a cache mount to /root/.yarn to speed up subsequent builds +RUN --mount=type=cache,target=/root/.yarn \ + yarn install --immutable && yarn pack + +# Stage 2: Build common module +FROM base as common +COPY --link --from=interfaces /usr/local/app/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz +COPY --link indexer-common/package.json indexer-common/tsconfig*.json yarn.lock ./ +COPY --link indexer-common/src src/ RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/interfaces']='file:/tmp/indexer-interfaces.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/common']='file:/tmp/indexer-common.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN yarn install -COPY --from=apiGatewayBuilder /usr/local/indexer-api-gateway/dist ./dist -RUN rm /tmp/indexer-interfaces.tgz /tmp/indexer-common.tgz +RUN --mount=type=cache,target=/root/.yarn \ + yarn install --immutable && yarn pack + +# Stage 3: Installing production dependecies +FROM base as deps +COPY --link --from=interfaces /usr/local/app/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz +COPY --link --from=common /usr/local/app/indexer-common-*.tgz /tmp/indexer-common.tgz +COPY --link indexer-api-gateway/package.json indexer-api-gateway/tsconfig*.json indexer-api-gateway/Gulpfile.mjs yarn.lock ./ +RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/interfaces']='file:/tmp/indexer-interfaces.tgz'; input.dependencies['@indexer/common']='file:/tmp/indexer-common.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" +RUN --mount=type=cache,target=/root/.yarn,sharing=private \ + yarn install --immutable --prod + +# Stage 4: Build service +FROM base as build +COPY --link --from=interfaces /usr/local/app/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz +COPY --link --from=common /usr/local/app/indexer-common-*.tgz /tmp/indexer-common.tgz +COPY --link --from=deps /usr/local/app/package.json /usr/local/app/tsconfig*.json /usr/local/app/Gulpfile.mjs /usr/local/app/yarn.lock ./ +COPY --link indexer-api-gateway/environments environments/ +COPY --link indexer-api-gateway/src src/ +RUN --mount=type=cache,target=/root/.yarn \ + yarn install --immutable && yarn run build:prod + +# Stage 5: Create the final image +FROM base as image +ENV NODE_ENV production + +# Copy the production dependencies from the deps stage and the built application from the build stage into the image +COPY --link --from=deps /usr/local/app/node_modules node_modules/ +COPY --link --from=deps /usr/local/app/package.json ./ +COPY --link --from=build /usr/local/app/dist dist/ + +# Change the user to node +USER node -CMD npm start +CMD [ "node", "dist/index.js" ] diff --git a/indexer-api-gateway/package.json b/indexer-api-gateway/package.json index 22f7e5bc46..90c4b4bf5a 100644 --- a/indexer-api-gateway/package.json +++ b/indexer-api-gateway/package.json @@ -14,8 +14,8 @@ }, "author": "Envision Blockchain Solutions ", "dependencies": { - "@indexer/interfaces": "^2.27.0", - "@indexer/common": "^2.27.0", + "@indexer/interfaces": "^2.27.1", + "@indexer/common": "^2.27.1", "@nestjs/common": "^9.4.1", "@nestjs/core": "^9.4.1", "@nestjs/microservices": "^9.4.1", @@ -85,5 +85,5 @@ "test": "mocha tests/**/*.test.js --reporter mocha-junit-reporter --reporter-options mochaFile=../test_results/ui-service.xml" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/indexer-api-gateway/src/api/services/search.ts b/indexer-api-gateway/src/api/services/search.ts index 859bd5f676..ecedd111cf 100644 --- a/indexer-api-gateway/src/api/services/search.ts +++ b/indexer-api-gateway/src/api/services/search.ts @@ -2,7 +2,7 @@ import { Controller, HttpCode, HttpStatus, Get, Query } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiQuery, ApiInternalServerErrorResponse } from '@nestjs/swagger'; import { IndexerMessageAPI } from '@indexer/common'; import { ApiClient } from '../api-client.js'; -import { ApiPaginatedResponse } from '../../decorators/api-paginated-response.js'; +import { ApiPaginatedResponse } from '#decorators'; import { InternalServerErrorDTO, SearchItemDTO } from '#dto'; @Controller('search') @@ -22,9 +22,19 @@ export class SearchApi extends ApiClient { name: 'pageIndex', description: 'Page index', example: 0, - required: false, + required: true, type: 'number', }) + @ApiQuery({ + name: 'pageSize', + description: 'Page size', + example: 10, + required: true, + schema: { + type: 'number', + maximum: 100 + } + }) @ApiQuery({ name: 'search', description: 'Search phrase', @@ -33,11 +43,13 @@ export class SearchApi extends ApiClient { @HttpCode(HttpStatus.OK) async search( @Query('pageIndex') pageIndex: number, + @Query('pageSize') pageSize: number, @Query('search') search?: string ): Promise { return await this.send(IndexerMessageAPI.GET_SEARCH_API, { search, pageIndex, + pageSize }); } } diff --git a/indexer-common/package.json b/indexer-common/package.json index 6b571b4cdb..0c004f745c 100644 --- a/indexer-common/package.json +++ b/indexer-common/package.json @@ -44,5 +44,5 @@ "test:stability": "mocha tests/stability.test.js" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/indexer-frontend/package.json b/indexer-frontend/package.json index f513b73a1a..e39ac7ae1a 100644 --- a/indexer-frontend/package.json +++ b/indexer-frontend/package.json @@ -1,7 +1,7 @@ { "author": "Envision Blockchain Solutions ", "name": "indexer-frontend", - "version": "2.27.0", + "version": "2.27.1", "scripts": { "ng": "ng", "start": "ng serve --proxy-config ./proxy.conf.json", diff --git a/indexer-frontend/src/app/components/header/header.component.html b/indexer-frontend/src/app/components/header/header.component.html index f68396b25b..f1fa988e90 100644 --- a/indexer-frontend/src/app/components/header/header.component.html +++ b/indexer-frontend/src/app/components/header/header.component.html @@ -20,7 +20,7 @@
+ [pageSizeOptions]="pageSizeOptions" [pageIndex]="pageIndex" [pageSize]="pageSize" [loading]="loading">
diff --git a/indexer-frontend/src/app/views/search/search.component.ts b/indexer-frontend/src/app/views/search/search.component.ts index 4990a491e1..758c5cf7bd 100644 --- a/indexer-frontend/src/app/views/search/search.component.ts +++ b/indexer-frontend/src/app/views/search/search.component.ts @@ -45,7 +45,9 @@ export class SearchViewComponent { public results: SearchItem[] = []; pageIndex: number = 0; + pageSize: number = 10; total: number = 0; + pageSizeOptions = [5, 10, 25, 100]; columns: any = [ { @@ -81,6 +83,7 @@ export class SearchViewComponent { this.setSearch(params['search']); if (params.pageIndex) { this.pageIndex = Number(params.pageIndex); + this.pageSize = Number(params.pageSize); } this.onSearch(); }); @@ -88,20 +91,25 @@ export class SearchViewComponent { ngOnDestroy(): void {} - public onPage(event: { pageIndex: number }) { + public onPage(event: { pageIndex: number, pageSize: number }) { this.pageIndex = event.pageIndex; + this.pageSize = event.pageSize; this.router.navigate([], { relativeTo: this.route, queryParams: { search: this.searchControl.value, pageIndex: this.pageIndex, + pageSize: this.pageSize, }, }); } public onSubmit() { this.pageIndex = 0; - this.onSearch(); + this.router.navigate([], { + relativeTo: this.route, + queryParams: { search: this.searchControl.value }, + }); } public setSearch(search: string) { @@ -114,7 +122,10 @@ export class SearchViewComponent { if (this.searchControl.valid && this.searchControl.value) { this.loading = true; this.searchService - .search(this.searchControl.value, this.pageIndex) + .search(this.searchControl.value, { + pageIndex: this.pageIndex, + pageSize: this.pageSize + }) .subscribe({ next: (result) => { const { items, total } = result; @@ -132,10 +143,6 @@ export class SearchViewComponent { } else { this.results = []; } - this.router.navigate([], { - relativeTo: this.route, - queryParams: { search: this.searchControl.value }, - }); } public onOpen(item: any) { diff --git a/indexer-interfaces/package.json b/indexer-interfaces/package.json index 7146574e17..597f551993 100644 --- a/indexer-interfaces/package.json +++ b/indexer-interfaces/package.json @@ -21,5 +21,5 @@ "prepack": "npm run build" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/indexer-service/Dockerfile b/indexer-service/Dockerfile index 244c987435..d71076ebbb 100644 --- a/indexer-service/Dockerfile +++ b/indexer-service/Dockerfile @@ -1,49 +1,60 @@ -FROM node:20 AS interfacesModuleBuilder -WORKDIR /usr/local/indexer-interfaces -COPY ./indexer-interfaces/package.json ./ -COPY ./indexer-interfaces/tsconfig*.json ./ -COPY ./yarn.lock ./ -COPY ./package-lock.json ./ -ADD ./indexer-interfaces/src ./src/. -RUN yarn install -RUN yarn pack - -FROM node:20 AS commonModuleBuilder -WORKDIR /usr/local/indexer-common -COPY --from=interfacesModuleBuilder /usr/local/indexer-interfaces/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz -COPY ./indexer-common/package.json ./ -COPY ./indexer-common/tsconfig*.json ./ -COPY ./yarn.lock ./ -COPY ./package-lock.json ./ -RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/interfaces']='file:/tmp/indexer-interfaces.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN yarn install -ADD ./indexer-common/src ./src/. -RUN yarn pack - -FROM node:20 AS serviceBuilder -WORKDIR /usr/local/indexer-service -COPY --from=interfacesModuleBuilder /usr/local/indexer-interfaces/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz -COPY --from=commonModuleBuilder /usr/local/indexer-common/indexer-common-*.tgz /tmp/indexer-common.tgz -COPY ./indexer-service/package.json ./ -COPY ./indexer-service/tsconfig*.json ./ -RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/interfaces']='file:/tmp/indexer-interfaces.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/common']='file:/tmp/indexer-common.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN yarn install -ADD ./indexer-service/src ./src/. -RUN yarn run build:prod - -FROM node:20 -ENV PLATFORM="docker" -ENV NODE_ENV="production" -WORKDIR /usr/local/indexer-service -COPY --from=interfacesModuleBuilder /usr/local/indexer-interfaces/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz -COPY --from=commonModuleBuilder /usr/local/indexer-common/indexer-common-*.tgz /tmp/indexer-common.tgz -COPY --from=serviceBuilder /usr/local/indexer-service/yarn.lock ./ -COPY ./indexer-service/package.json ./ +# syntax=docker/dockerfile:1 +# Stage 0: Use node image for base image for all stages +ARG NODE_VERSION=20.16-alpine +FROM node:${NODE_VERSION} as base +WORKDIR /usr/local/app +# Define an argument `YARN_CACHE_FOLDER` for the Yarn cache directory +ARG YARN_CACHE_FOLDER=/root/.yarn + +# Stage 1: Build interfaces module +FROM base as interfaces +COPY --link indexer-interfaces/package.json indexer-interfaces/tsconfig*.json yarn.lock ./ +COPY --link indexer-interfaces/src src/ +# Here and after. Leverage a cache mount to /root/.yarn to speed up subsequent builds +RUN --mount=type=cache,target=/root/.yarn \ + yarn install --immutable && yarn pack + +# Stage 2: Build common module +FROM base as common +COPY --link --from=interfaces /usr/local/app/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz +COPY --link indexer-common/package.json indexer-common/tsconfig*.json yarn.lock ./ +COPY --link indexer-common/src src/ RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/interfaces']='file:/tmp/indexer-interfaces.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/common']='file:/tmp/indexer-common.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN yarn install -COPY --from=serviceBuilder /usr/local/indexer-service/dist ./dist -RUN rm /tmp/indexer-interfaces.tgz /tmp/indexer-common.tgz +RUN --mount=type=cache,target=/root/.yarn \ + yarn install --immutable && yarn pack + +# Stage 3: Installing production dependecies +FROM base as deps +COPY --link --from=interfaces /usr/local/app/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz +COPY --link --from=common /usr/local/app/indexer-common-*.tgz /tmp/indexer-common.tgz +COPY --link indexer-service/package.json indexer-service/tsconfig*.json yarn.lock ./ +RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/interfaces']='file:/tmp/indexer-interfaces.tgz'; input.dependencies['@indexer/common']='file:/tmp/indexer-common.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" +RUN --mount=type=cache,target=/root/.yarn,sharing=private \ + yarn install --immutable --prod + +# Stage 4: Build service +FROM base as build +COPY --link --from=interfaces /usr/local/app/guardian-interfaces-*.tgz /tmp/interfaces.tgz +COPY --link --from=common /usr/local/app/guardian-common-*.tgz /tmp/common.tgz +COPY --link --from=deps /usr/local/app/package.json /usr/local/app/tsconfig*.json /usr/local/app/yarn.lock ./ +COPY --link indexer-service/src src/ +RUN --mount=type=cache,target=/root/.yarn \ + yarn install --immutable && yarn run build:prod + +# Stage 5: Create the final image +FROM base as image +ENV NODE_ENV production + +# Copy the production dependencies from the deps stage and the built application from the build stage into the image +COPY --link --from=deps /usr/local/app/node_modules node_modules/ +COPY --link --from=deps /usr/local/app/package.json ./ +COPY --link --from=build /usr/local/app/dist dist/ + +# Create necessary directories and set permissions +RUN mkdir -p /usr/local/app/dist/migrations && \ + chown -R node:node /usr/local/app + +# Change the user to node +USER node -CMD yarn start +CMD [ "node", "dist/index.js" ] diff --git a/indexer-service/package.json b/indexer-service/package.json index 387d52d7eb..ed7ffc15ba 100644 --- a/indexer-service/package.json +++ b/indexer-service/package.json @@ -2,8 +2,8 @@ "author": "Envision Blockchain Solutions ", "dependencies": { "@elastic/elasticsearch": "^8.12.2", - "@indexer/common": "^2.27.0", - "@indexer/interfaces": "^2.27.0", + "@indexer/common": "^2.27.1", + "@indexer/interfaces": "^2.27.1", "mongodb": "6.5.0", "@mikro-orm/core": "6.2.2", "@mikro-orm/mongodb": "6.2.2", @@ -60,5 +60,5 @@ }, "type": "module", "types": "dist/index.d.ts", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/indexer-service/src/api/search.service.ts b/indexer-service/src/api/search.service.ts index d7e1110f34..45d1d97ed6 100644 --- a/indexer-service/src/api/search.service.ts +++ b/indexer-service/src/api/search.service.ts @@ -15,13 +15,12 @@ export class SearchService { @MessagePattern(IndexerMessageAPI.GET_SEARCH_API) async search( @Payload() - msg: { - search: string; - pageSize?: number; - } + msg: { pageIndex: number, pageSize: number, search: string } ) { try { - msg.pageSize = 10; + if (!msg.pageIndex || !msg.pageSize) { + throw new Error('Invalid page parameters') + } const options = parsePageParams(msg); const { search } = msg; diff --git a/indexer-service/src/app.ts b/indexer-service/src/app.ts index f127f61ca0..967b547515 100644 --- a/indexer-service/src/app.ts +++ b/indexer-service/src/app.ts @@ -36,6 +36,7 @@ import { syncTopics, syncContracts } from './helpers/synchronizers/index.js'; +import { fixtures } from './helpers/fixtures.js'; const channelName = ( process.env.SERVICE_CHANNEL || `indexer-service.${Utils.GenerateUUIDv4(26)}` @@ -144,6 +145,10 @@ Promise.all([ } ); } + /** + * Fixtures + */ + fixtures(); /** * Listen */ diff --git a/indexer-service/src/helpers/fixtures.ts b/indexer-service/src/helpers/fixtures.ts new file mode 100644 index 0000000000..05d2a74d38 --- /dev/null +++ b/indexer-service/src/helpers/fixtures.ts @@ -0,0 +1,19 @@ +import { Analytics, DataBaseHelper } from '@indexer/common'; + +/** + * Create default entities + */ +export async function fixtures(): Promise { + const em = DataBaseHelper.getEntityManager(); + if ((await em.count(Analytics)) === 0) { + await em.persistAndFlush( + em.create(Analytics, { + registries: 0, + methodologies: 0, + projects: 0, + totalIssuance: 0, + date: new Date(), + }) + ); + } +} diff --git a/indexer-web-proxy/Dockerfile b/indexer-web-proxy/Dockerfile index 94ddf2fa8b..56ff7b815c 100644 --- a/indexer-web-proxy/Dockerfile +++ b/indexer-web-proxy/Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 # Stage 0: Use node image for base image for all stages -ARG NODE_VERSION=20.11.1-alpine +ARG NODE_VERSION=20.16-alpine FROM node:${NODE_VERSION} as base WORKDIR /usr/local/app # Define an argument `YARN_CACHE_FOLDER` for the Yarn cache directory @@ -12,7 +12,7 @@ COPY --link indexer-interfaces/package.json indexer-interfaces/tsconfig*.json ya COPY --link indexer-interfaces/src src/ # Leverage a cache mount to /root/.yarn to speed up subsequent builds RUN --mount=type=cache,target=/root/.yarn \ - yarn install --frozen-lockfile && yarn pack + yarn install --immutable && yarn pack # Stage 2: Build frontend FROM base as build @@ -21,7 +21,7 @@ COPY --link ./indexer-frontend/. ./ RUN npm install indexer-interfaces.tgz && npm run build # Stage 3: Create the final image -FROM nginxinc/nginx-unprivileged:1.25.4-alpine as image +FROM nginxinc/nginx-unprivileged:1.27-alpine as image # Copy config and built application from the build stage into the image COPY --link ./indexer-web-proxy/configs/default.conf /etc/nginx/conf.d/default.conf diff --git a/indexer-worker-service/Dockerfile b/indexer-worker-service/Dockerfile index 476160c36c..d7f71df8c2 100644 --- a/indexer-worker-service/Dockerfile +++ b/indexer-worker-service/Dockerfile @@ -1,49 +1,60 @@ -FROM node:20 AS interfacesModuleBuilder -WORKDIR /usr/local/indexer-interfaces -COPY ./indexer-interfaces/package.json ./ -COPY ./indexer-interfaces/tsconfig*.json ./ -COPY ./yarn.lock ./ -COPY ./package-lock.json ./ -ADD ./indexer-interfaces/src ./src/. -RUN yarn install -RUN yarn pack - -FROM node:20 AS commonModuleBuilder -WORKDIR /usr/local/indexer-common -COPY --from=interfacesModuleBuilder /usr/local/indexer-interfaces/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz -COPY ./indexer-common/package.json ./ -COPY ./indexer-common/tsconfig*.json ./ -COPY ./yarn.lock ./ -COPY ./package-lock.json ./ -RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/interfaces']='file:/tmp/indexer-interfaces.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN yarn install -ADD ./indexer-common/src ./src/. -RUN yarn pack - -FROM node:20 AS workerServiceBuilder -WORKDIR /usr/local/indexer-worker-service -COPY --from=interfacesModuleBuilder /usr/local/indexer-interfaces/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz -COPY --from=commonModuleBuilder /usr/local/indexer-common/indexer-common-*.tgz /tmp/indexer-common.tgz -COPY ./indexer-worker-service/package.json ./ -COPY ./indexer-worker-service/tsconfig*.json ./ -RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/interfaces']='file:/tmp/indexer-interfaces.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/common']='file:/tmp/indexer-common.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN yarn install -ADD ./indexer-worker-service/src ./src/. -RUN yarn run build:prod - -FROM node:20 -ENV PLATFORM="docker" -ENV NODE_ENV="production" -WORKDIR /usr/local/indexer-worker-service -COPY --from=interfacesModuleBuilder /usr/local/indexer-interfaces/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz -COPY --from=commonModuleBuilder /usr/local/indexer-common/indexer-common-*.tgz /tmp/indexer-common.tgz -COPY --from=workerServiceBuilder /usr/local/indexer-worker-service/yarn.lock ./ -COPY ./indexer-worker-service/package.json ./ +# syntax=docker/dockerfile:1 +# Stage 0: Use node image for base image for all stages +ARG NODE_VERSION=20.16-alpine +FROM node:${NODE_VERSION} as base +WORKDIR /usr/local/app +# Define an argument `YARN_CACHE_FOLDER` for the Yarn cache directory +ARG YARN_CACHE_FOLDER=/root/.yarn + +# Stage 1: Build interfaces module +FROM base as interfaces +COPY --link indexer-interfaces/package.json indexer-interfaces/tsconfig*.json yarn.lock ./ +COPY --link indexer-interfaces/src src/ +# Here and after. Leverage a cache mount to /root/.yarn to speed up subsequent builds +RUN --mount=type=cache,target=/root/.yarn \ + yarn install --immutable && yarn pack + +# Stage 2: Build common module +FROM base as common +COPY --link --from=interfaces /usr/local/app/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz +COPY --link indexer-common/package.json indexer-common/tsconfig*.json yarn.lock ./ +COPY --link indexer-common/src src/ RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/interfaces']='file:/tmp/indexer-interfaces.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/common']='file:/tmp/indexer-common.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" -RUN yarn install -COPY --from=workerServiceBuilder /usr/local/indexer-worker-service/dist ./dist -RUN rm /tmp/indexer-interfaces.tgz /tmp/indexer-common.tgz +RUN --mount=type=cache,target=/root/.yarn \ + yarn install --immutable && yarn pack + +# Stage 3: Installing production dependecies +FROM base as deps +COPY --link --from=interfaces /usr/local/app/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz +COPY --link --from=common /usr/local/app/indexer-common-*.tgz /tmp/indexer-common.tgz +COPY --link indexer-worker-service/package.json indexer-worker-service/tsconfig*.json yarn.lock ./ +RUN node -e "const fs=require('fs'); const input=JSON.parse(fs.readFileSync('package.json')); input.dependencies['@indexer/interfaces']='file:/tmp/indexer-interfaces.tgz'; input.dependencies['@indexer/common']='file:/tmp/indexer-common.tgz'; fs.writeFileSync('package.json', JSON.stringify(input));" +RUN --mount=type=cache,target=/root/.yarn,sharing=private \ + yarn install --immutable --prod + +# Stage 4: Build service +FROM base as build +COPY --link --from=interfaces /usr/local/app/indexer-interfaces-*.tgz /tmp/indexer-interfaces.tgz +COPY --link --from=common /usr/local/app/indexer-common-*.tgz /tmp/indexer-common.tgz +COPY --link --from=deps /usr/local/app/package.json /usr/local/app/tsconfig*.json /usr/local/app/yarn.lock ./ +COPY --link indexer-worker-service/src src/ +RUN --mount=type=cache,target=/root/.yarn \ + yarn install --immutable && yarn run build:prod + +# Stage 5: Create the final image +FROM base as image +ENV NODE_ENV production + +# Copy the production dependencies from the deps stage and the built application from the build stage into the image +COPY --link --from=deps /usr/local/app/node_modules node_modules/ +COPY --link --from=deps /usr/local/app/package.json ./ +COPY --link --from=build /usr/local/app/dist dist/ + +# Create necessary directories and set permissions +RUN mkdir -p /usr/local/app/dist/migrations && \ + chown -R node:node /usr/local/app + +# Change the user to node +USER node -CMD yarn start +CMD [ "node", "dist/index.js" ] diff --git a/indexer-worker-service/package.json b/indexer-worker-service/package.json index 1d900a744f..7c396f72df 100644 --- a/indexer-worker-service/package.json +++ b/indexer-worker-service/package.json @@ -1,8 +1,8 @@ { "author": "Envision Blockchain Solutions ", "dependencies": { - "@indexer/interfaces": "^2.27.0", - "@indexer/common": "^2.27.0", + "@indexer/interfaces": "^2.27.1", + "@indexer/common": "^2.27.1", "@nestjs/common": "^9.4.1", "@nestjs/core": "^9.4.1", "@nestjs/microservices": "^9.4.1", @@ -55,5 +55,5 @@ }, "type": "module", "types": "dist/index.d.ts", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/interfaces/package.json b/interfaces/package.json index b6bbc97cc4..928243e217 100644 --- a/interfaces/package.json +++ b/interfaces/package.json @@ -33,5 +33,5 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/logger-service/package.json b/logger-service/package.json index e8b777fab6..a4be1adce9 100644 --- a/logger-service/package.json +++ b/logger-service/package.json @@ -5,8 +5,8 @@ "image-size": "1.0.2" }, "dependencies": { - "@guardian/common": "^2.27.0", - "@guardian/interfaces": "^2.27.0", + "@guardian/common": "^2.27.1", + "@guardian/interfaces": "^2.27.1", "@mikro-orm/core": "6.2.2", "@mikro-orm/mongodb": "6.2.2", "@nestjs/common": "^9.4.1", @@ -57,5 +57,5 @@ "watch": "nodemon src/index.ts" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/mrv-sender/package.json b/mrv-sender/package.json index d6d1f4261f..37bcf8a732 100644 --- a/mrv-sender/package.json +++ b/mrv-sender/package.json @@ -5,7 +5,7 @@ "image-size": "1.0.2" }, "dependencies": { - "@guardian/common": "^2.27.0", + "@guardian/common": "^2.27.1", "@transmute/credentials-context": "0.7.0-unstable.80", "@transmute/did-context": "0.7.0-unstable.80", "@transmute/ed25519-signature-2018": "0.7.0-unstable.80", @@ -44,5 +44,5 @@ "start": "node dist/index.js" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/notification-service/package.json b/notification-service/package.json index a78823fa6e..e0fadb0699 100644 --- a/notification-service/package.json +++ b/notification-service/package.json @@ -5,8 +5,8 @@ "image-size": "1.0.2" }, "dependencies": { - "@guardian/common": "^2.27.0", - "@guardian/interfaces": "^2.27.0", + "@guardian/common": "^2.27.1", + "@guardian/interfaces": "^2.27.1", "@mikro-orm/core": "6.2.2", "@mikro-orm/mongodb": "6.2.2", "@nestjs/common": "^9.4.1", @@ -56,5 +56,5 @@ "watch": "nodemon src/index.ts" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/package.json b/package.json index 0b9a3fa3fe..e9de94fc36 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "indexer-service", "indexer-worker-service" ], - "version": "2.27.0", + "version": "2.27.1", "devDependencies": { "detect-secrets": "^1.0.6" }, diff --git a/policy-service/package.json b/policy-service/package.json index f256186470..394b739e24 100644 --- a/policy-service/package.json +++ b/policy-service/package.json @@ -15,8 +15,8 @@ "image-size": "1.0.2" }, "dependencies": { - "@guardian/common": "2.27.0", - "@guardian/interfaces": "2.27.0", + "@guardian/common": "2.27.1", + "@guardian/interfaces": "2.27.1", "@hashgraph/sdk": "2.46.0", "@mattrglobal/jsonld-signatures-bbs": "^1.1.2", "@meeco/cryppo": "2.0.2", @@ -100,5 +100,5 @@ "test:stability": "mocha tests/stability.test.js" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/policy-service/src/policy-engine/blocks/documents-source.ts b/policy-service/src/policy-engine/blocks/documents-source.ts index 8afba08128..9364e00197 100644 --- a/policy-service/src/policy-engine/blocks/documents-source.ts +++ b/policy-service/src/policy-engine/blocks/documents-source.ts @@ -87,7 +87,7 @@ export class InterfaceDocumentsSource { queryParams = {}; } - const {itemsPerPage, page, size, filterByUUID, ...filterIds} = queryParams; + const {itemsPerPage, page, size, filterByUUID, sortDirection, sortField, useStrict, ...filterIds} = queryParams; const filterAddons = ref.getFiltersAddons(); const filters = filterAddons.map(addon => { @@ -100,11 +100,17 @@ export class InterfaceDocumentsSource { if (filterIds) { for (const filterId of Object.keys(filterIds)) { + const filterValue = filterIds[filterId]; + const filter = filterAddons.find((_filter) => { return (_filter.uuid === filterId) || (_filter.tag === filterId); }); if (filter) { - await (filter as IPolicyAddonBlock).setFilterState(user, {filterValue: filterIds[filterId]}); + if (useStrict === 'true') { + await (filter as IPolicyAddonBlock).setFiltersStrict(user, {filterValue}); + } else { + await (filter as IPolicyAddonBlock).setFilterState(user, {filterValue}); + } } } } @@ -125,8 +131,11 @@ export class InterfaceDocumentsSource { let paginationData = null; if (pagination) { - if (itemsPerPage && page) { - await pagination.setState(user, {itemsPerPage, page, size}); + if ((!isNaN(page)) && (!isNaN(itemsPerPage))) { + await pagination.setState(user, { + itemsPerPage: parseInt(itemsPerPage, 10), + page: parseInt(page, 10), + }); } paginationData = await pagination.getState(user); @@ -136,8 +145,15 @@ export class InterfaceDocumentsSource { return addon.blockType === 'historyAddon'; }) as IPolicyAddonBlock; - const enableCommonSorting = ref.options.uiMetaData.enableSorting; - const sortState = this.state[user.id] || {}; + const enableCommonSorting = ref.options.uiMetaData.enableSorting || (sortDirection && sortField); + let sortState = this.state[user.id] || {}; + if (sortDirection && sortField) { + sortState = { + orderDirection: sortDirection, + orderField: sortField + }; + this.state[user.id] = sortState; + } let data: any = enableCommonSorting ? await this.getDataByAggregationFilters(ref, user, sortState, paginationData, history) : await ref.getGlobalSources(user, paginationData); @@ -158,14 +174,14 @@ export class InterfaceDocumentsSource { state.document, history ? history.options.timelineLabelPath || - 'option.status' + 'option.status' : 'option.status' ), comment: ObjGet( state.document, history ? history.options.timelineDescriptionPath || - 'option.comment' + 'option.comment' : 'option.comment' ), created: state.createDate, @@ -184,6 +200,19 @@ export class InterfaceDocumentsSource { data = [doc]; } + if (filterIds) { + for (const filterId of Object.keys(filterIds)) { + const filter = filterAddons.find((_filter) => { + return (_filter.uuid === filterId) || (_filter.tag === filterId); + }); + if (filter) { + if (useStrict === 'true') { + await (filter as IPolicyAddonBlock).resetFilters(user); + } + } + } + } + return Object.assign( { data, diff --git a/policy-service/src/policy-engine/blocks/filters-addon-block.ts b/policy-service/src/policy-engine/blocks/filters-addon-block.ts index 729e768971..97fd4c5aff 100644 --- a/policy-service/src/policy-engine/blocks/filters-addon-block.ts +++ b/policy-service/src/policy-engine/blocks/filters-addon-block.ts @@ -39,6 +39,8 @@ export class FiltersAddonBlock { } } + private readonly previousState: { [key: string]: any } = {}; + /** * Block state * @private @@ -96,6 +98,9 @@ export class FiltersAddonBlock { name: findOptions(e, ref.options.optionName), value: findOptions(e, ref.options.optionValue), } + }).filter((value, index, array) => { + const i = array.findIndex(v => v.value === value.value); + return i === index; }); block.data = blockState.lastData; block.optionName = ref.options.optionName; @@ -107,6 +112,40 @@ export class FiltersAddonBlock { return block; } + async resetFilters(user: PolicyUser): Promise { + if (this.previousState[user.id]) { + this.state[user.id] = this.previousState[user.id]; + delete this.previousState[user.id]; + } + } + + async setFiltersStrict(user: PolicyUser, data: any) { + const ref = PolicyComponentsUtils.GetBlockRef(this); + this.previousState[user.id] = this.state[user.id]; + const filter: any = {}; + if (!data) { + throw new BlockActionError(`filter value is unknown`, ref.blockType, ref.uuid) + } + if (ref.options.type === 'dropdown') { + const value = data.filterValue; + const blockState = this.state[user.id] || {}; + if (!blockState.lastData) { + await this.getData(user); + } + + if (value) { + filter[ref.options.field] = value; + } + + if (!ref.options.canBeEmpty) { + throw new BlockActionError(`filter value is unknown`, ref.blockType, ref.uuid) + } + blockState.lastValue = value; + this.state[user.id] = blockState; + } + ref.setFilters(filter, user); + } + async setFilterState(user: PolicyUser, data: any): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); const filter: any = {}; @@ -119,7 +158,7 @@ export class FiltersAddonBlock { if (!blockState.lastData) { await this.getData(user); } - const selectItem = blockState.lastData.find((e: any) => e.value === value); + const selectItem = Array.isArray(blockState.lastData) ? blockState.lastData.find((e: any) => e.value === value) : null; if (selectItem) { filter[ref.options.field] = selectItem.value; } else if (!ref.options.canBeEmpty) { diff --git a/policy-service/src/policy-engine/helpers/decorators/data-source-block.ts b/policy-service/src/policy-engine/helpers/decorators/data-source-block.ts index 333e194499..04116b9d41 100644 --- a/policy-service/src/policy-engine/helpers/decorators/data-source-block.ts +++ b/policy-service/src/policy-engine/helpers/decorators/data-source-block.ts @@ -140,11 +140,28 @@ export function DataSourceBlock(options: Partial) { let totalCount = 0; let currentPosition = 0; + const _globalFilters = {} as any; + for (const key in globalFilters) { + if (!isNaN(globalFilters[key].$eq)) { + if (!_globalFilters.$or) { + _globalFilters.$or = []; + } + const filter1 = {} as any; + filter1[key] = {$eq: String(globalFilters[key].$eq)}; + _globalFilters.$or.push(filter1); + const filter2 = {} as any; + filter2[key] = {$eq: Number(globalFilters[key].$eq)}; + _globalFilters.$or.push(filter2); + } else { + _globalFilters[key] = globalFilters[key]; + } + } + const resultsCountArray = []; const sourceAddons = this.children.filter(c => c.blockClassName === 'SourceAddon'); for (const addon of sourceAddons) { - const resultCount = await addon.getFromSource(user, globalFilters, true); + const resultCount = await addon.getFromSource(user, _globalFilters, true); totalCount += resultCount; resultsCountArray.push(resultCount); } @@ -158,7 +175,7 @@ export function DataSourceBlock(options: Partial) { // If pagination block is not set if (!paginationData) { - for (const item of await currentSource.getFromSource(user, globalFilters, false, null)) { + for (const item of await currentSource.getFromSource(user, _globalFilters, false, null)) { (data as any[]).push(item); } continue; @@ -183,7 +200,7 @@ export function DataSourceBlock(options: Partial) { skip = Math.max(start - previousCount, 0); limit = paginationData.itemsPerPage - Math.min((previousCount - start), 0); - const childData = await currentSource.getFromSource(user, globalFilters, false, { + const childData = await currentSource.getFromSource(user, _globalFilters, false, { offset: skip, limit: limit - currentPosition }); diff --git a/policy-service/src/policy-engine/policy-engine.interface.ts b/policy-service/src/policy-engine/policy-engine.interface.ts index c2b864e66d..3027a8fe7d 100644 --- a/policy-service/src/policy-engine/policy-engine.interface.ts +++ b/policy-service/src/policy-engine/policy-engine.interface.ts @@ -612,6 +612,16 @@ export interface IPolicyAddonBlock extends IPolicyBlock { * Get selective attributes addons */ getSelectiveAttributes(): IPolicyAddonBlock[]; + + /** + * Set strict filters + */ + setFiltersStrict(user: PolicyUser | null, data: any): Promise; + + /** + * Restore filters + */ + resetFilters(user: PolicyUser): Promise; } /** diff --git a/queue-service/package.json b/queue-service/package.json index 99885e2110..865813016f 100644 --- a/queue-service/package.json +++ b/queue-service/package.json @@ -2,8 +2,8 @@ "author": "Envision Blockchain Solutions ", "dependencies": { "@filebase/client": "^0.0.5", - "@guardian/common": "^2.27.0", - "@guardian/interfaces": "^2.27.0", + "@guardian/common": "^2.27.1", + "@guardian/interfaces": "^2.27.1", "@hashgraph/sdk": "2.34.1", "@nestjs/common": "^9.4.1", "@nestjs/core": "^9.4.1", @@ -66,5 +66,5 @@ }, "type": "module", "types": "dist/index.d.ts", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/swagger-analytics.yaml b/swagger-analytics.yaml index bc57381f1c..a3c2ecb53a 100644 --- a/swagger-analytics.yaml +++ b/swagger-analytics.yaml @@ -208,7 +208,7 @@ info: the heart of the Guardian solution is a sophisticated Policy Workflow Engine (PWE) that enables applications to offer a requirements-based tokenization implementation. - version: 2.27.0 + version: 2.27.1 contact: name: API developer url: https://envisionblockchain.com diff --git a/swagger-indexer.yaml b/swagger-indexer.yaml index 67991a6101..68c28ac46f 100644 --- a/swagger-indexer.yaml +++ b/swagger-indexer.yaml @@ -7,12 +7,20 @@ paths: description: Full-text indexer search parameters: - name: pageIndex - required: false + required: true in: query description: Page index example: 0 schema: type: number + - name: pageSize + required: true + in: query + description: Page size + example: 10 + schema: + type: number + maximum: 100 - name: search required: true in: query @@ -1840,7 +1848,7 @@ info: the heart of the Guardian solution is a sophisticated Policy Workflow Engine (PWE) that enables applications to offer a requirements-based tokenization implementation. - version: 2.27.0 + version: 2.27.1 contact: name: API developer url: https://envisionblockchain.com diff --git a/swagger.yaml b/swagger.yaml index 039b3820c9..dac4aa049f 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -11892,7 +11892,7 @@ info: the heart of the Guardian solution is a sophisticated Policy Workflow Engine (PWE) that enables applications to offer a requirements-based tokenization implementation. - version: 2.27.0 + version: 2.27.1 contact: name: API developer url: https://envisionblockchain.com diff --git a/topic-viewer/package.json b/topic-viewer/package.json index 253473e488..b921ff93ed 100644 --- a/topic-viewer/package.json +++ b/topic-viewer/package.json @@ -30,5 +30,5 @@ "start": "node dist/index.js" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/tree-viewer/package.json b/tree-viewer/package.json index c21a87da98..b8bdb35433 100644 --- a/tree-viewer/package.json +++ b/tree-viewer/package.json @@ -28,5 +28,5 @@ "start": "node dist/index.js" }, "type": "module", - "version": "2.27.0" + "version": "2.27.1" } diff --git a/worker-service/package.json b/worker-service/package.json index f7bf7a2b04..3820c929ec 100644 --- a/worker-service/package.json +++ b/worker-service/package.json @@ -2,8 +2,8 @@ "author": "Envision Blockchain Solutions ", "dependencies": { "@filebase/client": "^0.0.5", - "@guardian/common": "^2.27.0", - "@guardian/interfaces": "^2.27.0", + "@guardian/common": "^2.27.1", + "@guardian/interfaces": "^2.27.1", "@hashgraph/sdk": "2.46.0", "@nestjs/common": "^9.4.1", "@nestjs/core": "^9.4.1", @@ -69,5 +69,5 @@ }, "type": "module", "types": "dist/index.d.ts", - "version": "2.27.0" + "version": "2.27.1" }