From 7c3ccc35af5914adb86427f2279445156603920b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thea=20Sch=C3=B6bl?= Date: Wed, 31 May 2023 11:40:08 +0000 Subject: [PATCH 1/2] fix: search uses inactive indices --- src/storage/elasticsearch/elasticsearch.ts | 194 +++++++----------- src/storage/elasticsearch/util/index.ts | 21 +- .../elasticsearch/elasticsearch.spec.ts | 71 +++---- 3 files changed, 124 insertions(+), 162 deletions(-) diff --git a/src/storage/elasticsearch/elasticsearch.ts b/src/storage/elasticsearch/elasticsearch.ts index 02ca1e2e..f3c52d41 100644 --- a/src/storage/elasticsearch/elasticsearch.ts +++ b/src/storage/elasticsearch/elasticsearch.ts @@ -18,7 +18,6 @@ import { AggregateName, AggregationsMultiTermsBucket, IndicesGetAliasResponse, - IndicesUpdateAliasesAction, SearchHit, SearchResponse, } from '@elastic/elasticsearch/lib/api/types'; @@ -38,8 +37,13 @@ import { ElasticsearchQueryDisMaxConfig, ElasticsearchQueryQueryStringConfig, } from './types/elasticsearch-config'; -import {ALL_INDICES_QUERY, getThingIndexName, parseIndexName, VALID_INDEX_REGEX} from './util'; -import {removeInvalidAliasChars} from './util/alias'; +import { + ACTIVE_INDICES_ALIAS, + getThingIndexName, + INACTIVE_INDICES_ALIAS, + matchIndexByType, + VALID_INDEX_REGEX, +} from './util'; import {noUndefined} from './util/no-undefined'; import {retryCatch, RetryOptions} from './util/retry'; @@ -47,17 +51,6 @@ import {retryCatch, RetryOptions} from './util/retry'; * A database interface for elasticsearch */ export class Elasticsearch implements Database { - /** - * Holds a map of all elasticsearch indices that are available to search - */ - aliasMap: { - // each scType has an alias which can contain multiple sources - [scType: string]: { - // each source is assigned an index name in elasticsearch - [source: string]: string; - }; - }; - /** * Elasticsearch client */ @@ -112,7 +105,6 @@ export class Elasticsearch implements Database { } }); - this.aliasMap = {}; this.ready = false; this.mailQueue = mailQueue; @@ -121,7 +113,7 @@ export class Elasticsearch implements Database { /** * Gets a map which contains each alias and all indices that are associated with each alias */ - private async getAliasMap(retryOptions: Partial> = {}) { + private async cleanupDeadIndices(retryOptions: Partial> = {}) { const aliasResponse = await retryCatch({ maxRetries: 10, retryInterval: 2000, @@ -136,31 +128,18 @@ export class Elasticsearch implements Database { ...retryOptions, }); - const aliases = Object.entries(aliasResponse) - .filter(([index]) => !index.startsWith('.')) - .map(([index, alias]) => ({ - index, - alias, - ...parseIndexName(index), - })); - - for (const {type, index, source} of aliases.filter(({type, alias}) => type in alias.aliases)) { - this.aliasMap[type] = this.aliasMap[type] || {}; - this.aliasMap[type][source] = index; - } - this.ready = true; - const unusedIndices = aliases.filter(({type, alias}) => !(type in alias.aliases)).map(({index}) => index); - if (unusedIndices.length > 0) { - await this.client.indices.delete({ - index: unusedIndices, - }); - Logger.warn(`Deleted old indices: oldIndicesToDelete`); - } + const inactiveIndices = Object.entries(aliasResponse) + .filter(([_, aliases]) => Object.keys(aliases.aliases).includes(INACTIVE_INDICES_ALIAS)) + .map(([indexName]) => indexName); - // eslint-disable-next-line unicorn/no-null - Logger.ok(`Read alias map from elasticsearch: ${JSON.stringify(this.aliasMap, null, 2)}`); + if (inactiveIndices.length > 0) { + await this.client.indices.delete({ + index: inactiveIndices, + }); + Logger.warn(`Deleted old indices: ${inactiveIndices}`); + } } /** @@ -181,7 +160,8 @@ export class Elasticsearch implements Database { }, }, from: 0, - index: ALL_INDICES_QUERY, + allow_no_indices: true, + index: ACTIVE_INDICES_ALIAS, size: 1, }); @@ -189,17 +169,12 @@ export class Elasticsearch implements Database { return searchResponse.hits.hits[0]; } - private async prepareBulkWrite(bulk: Bulk): Promise<{index: string; alias: string}> { + private async prepareBulkWrite(bulk: Bulk): Promise { if (!this.ready) { throw new Error('No connection to elasticsearch established yet.'); } const index = getThingIndexName(bulk.type, bulk.source, bulk); - const alias = removeInvalidAliasChars(bulk.type, bulk.uid); - - if (typeof this.aliasMap[alias] === 'undefined') { - this.aliasMap[alias] = {}; - } if (!VALID_INDEX_REGEX.test(index)) { throw new Error( @@ -208,21 +183,24 @@ export class Elasticsearch implements Database { ); } - return {index, alias}; + return index; } /** - * Should be called, when a new bulk was created. Creates a new index and applies the mapping to the index + * Should be called when a new bulk was created. Creates a new index and applies the mapping to the index * * @param bulk the bulk process that was created */ public async bulkCreated(bulk: Bulk): Promise { - const {index} = await this.prepareBulkWrite(bulk); + const index = await this.prepareBulkWrite(bulk); // re-apply the index template before each new bulk operation await putTemplate(this.client, bulk.type); await this.client.indices.create({ index, + aliases: { + [INACTIVE_INDICES_ALIAS]: {}, + }, }); Logger.info('Created index', index); @@ -234,7 +212,7 @@ export class Elasticsearch implements Database { * @param bulk the bulk process that is expired */ public async bulkExpired(bulk: Bulk): Promise { - const index: string = getThingIndexName(bulk.type, bulk.source, bulk); + const index = await this.prepareBulkWrite(bulk); Logger.info('Bulk expired. Deleting index', index); @@ -248,57 +226,38 @@ export class Elasticsearch implements Database { /** * Should be called when a bulk process is updated (replaced by a newer bulk). This will replace the old - * index and publish all data, that was index in the new instead + * index and publish all data that was indexed in the new instead * - * @param bulk the new bulk process that should replace the old one with same type and source + * @param bulk the new bulk process that should replace the old one with the same type and source */ public async bulkUpdated(bulk: Bulk): Promise { - const {index, alias} = await this.prepareBulkWrite(bulk); + const index = await this.prepareBulkWrite(bulk); - // create the new index if it does not exist - // eslint-disable-next-line unicorn/no-await-expression-member - if (!(await this.client.indices.exists({index}))) { - // re-apply the index template before each new bulk operation - await putTemplate(this.client, bulk.type); - await this.client.indices.create({ - index, - }); - } + await this.client.indices.refresh({index, allow_no_indices: false}); - // get the old index from our aliasMap - const oldIndex: string = this.aliasMap[alias][bulk.source]; + const activeIndices = await this.client.indices + .getAlias({ + index: matchIndexByType(bulk.type, bulk.source), + name: ACTIVE_INDICES_ALIAS, + }) + .then(it => Object.entries(it).map(([name]) => name)) + .catch(() => [] as string[]); - // add our new index to the alias - // this was type safe with @types/elasticsearch, the new package however provides no type definitions - const actions: IndicesUpdateAliasesAction[] = [ - { - add: {index: index, alias: alias}, - }, - ]; - - // remove our old index if it exists - // noinspection SuspiciousTypeOfGuard - if (typeof oldIndex === 'string') { - actions.push({ - remove: {index: oldIndex, alias: alias}, - }); - } - - // refresh the index (fsync changes) - await this.client.indices.refresh({index}); - - // execute our alias actions - await this.client.indices.updateAliases({actions}); - - // swap the index in our aliasMap - this.aliasMap[alias][bulk.source] = index; - // noinspection SuspiciousTypeOfGuard - if (typeof oldIndex === 'string') { - // delete the old index - await this.client.indices.delete({index: oldIndex}); - Logger.info('deleted old index', oldIndex); - } - Logger.info('swapped alias index alias', oldIndex, '=>', index); + await this.client.indices.updateAliases({ + actions: [ + { + add: {index, alias: ACTIVE_INDICES_ALIAS}, + }, + { + remove: {index, alias: INACTIVE_INDICES_ALIAS}, + }, + ...activeIndices.map(index => ({ + remove_index: {index}, + })), + ], + }); + Logger.info(`Index for ${bulk.type} is now ${index}`); + Logger.info(`Also removed obsolete indices ${activeIndices}`); } /** @@ -332,7 +291,7 @@ export class Elasticsearch implements Database { await Monitoring.setUp(monitoringConfiguration, this.client, this.mailQueue); } - return this.getAliasMap(retryOptions); + return this.cleanupDeadIndices(retryOptions); } /** @@ -342,35 +301,34 @@ export class Elasticsearch implements Database { * @param bulk the bulk process which item belongs to */ public async post(object: SCThings, bulk: Bulk): Promise { + const index = await this.prepareBulkWrite(bulk); const thing: SCThings & {creation_date: string} = { ...object, creation_date: moment().format(), }; - const item = await this.getObject(object.uid); - - // check that the item will get replaced if the index is rolled over (index with the same name excluding ending uid) - if (typeof item !== 'undefined') { - const indexOfNew = getThingIndexName(thing.type, bulk.source, bulk); - const oldIndex = item._index; - - // new item doesn't replace the old one - if ( - oldIndex.slice(0, Math.max(0, oldIndex.lastIndexOf('_'))) !== - indexOfNew.slice(0, Math.max(0, indexOfNew.lastIndexOf('_'))) - ) { - throw new Error( - // eslint-disable-next-line unicorn/no-null - `Object "${thing.uid}" already exists. Object was: ${JSON.stringify(thing, null, 2)}`, - ); - } + const conflictingThing = await this.client.search({ + query: { + term: { + 'uid.raw': { + value: thing.uid, + }, + }, + }, + // matches all indices but excludes indices of the same type + // https://www.elastic.co/guide/en/elasticsearch/reference/7.14/multi-index.html#multi-index + index: ['stapps_*', `-${matchIndexByType(bulk.type, bulk.source)}`], + }); + if (conflictingThing.hits.hits.length > 0) { + throw new Error( + `UID conflict: ${thing.uid}. ${index} tried to post an object that already exists but which it won't replace.`, + ); } - // regular bulk update (item gets replaced when bulk is updated) const searchResponse = await this.client.create({ document: thing, id: thing.uid, - index: getThingIndexName(thing.type, bulk.source, bulk), + index, timeout: '90s', }); @@ -423,15 +381,15 @@ export class Elasticsearch implements Database { | undefined, }; - const query = { + const response: SearchResponse = await this.client.search({ aggs: aggregations, query: buildQuery(parameters, this.config, esConfig), from: parameters.from, - index: ALL_INDICES_QUERY, + index: ACTIVE_INDICES_ALIAS, + allow_no_indices: true, size: parameters.size, sort: typeof parameters.sort !== 'undefined' ? buildSort(parameters.sort) : undefined, - }; - const response: SearchResponse = await this.client.search(query); + }); return { data: response.hits.hits diff --git a/src/storage/elasticsearch/util/index.ts b/src/storage/elasticsearch/util/index.ts index 24ba5999..4b037891 100644 --- a/src/storage/elasticsearch/util/index.ts +++ b/src/storage/elasticsearch/util/index.ts @@ -6,9 +6,14 @@ import {SCBulkResponse, SCThingType, SCUuid} from '@openstapps/core'; export const INDEX_UID_LENGTH = 8; /** - * A string which matches all indices + * Matches all active indices */ -export const ALL_INDICES_QUERY = 'stapps_*_*_*'; +export const ACTIVE_INDICES_ALIAS = 'stapps_active'; + +/** + * Matches all inactive aliases + */ +export const INACTIVE_INDICES_ALIAS = 'stapps_inactive'; /** * Matches index names such as stapps___ @@ -45,12 +50,14 @@ export function parseIndexName(index: string): ParsedIndexName { * @param bulk bulk process which created this index */ export function getThingIndexName(type: SCThingType, source: string, bulk: SCBulkResponse) { - let out = type.toLowerCase(); - while (out.includes(' ')) { - out = out.replace(' ', '_'); - } + return `stapps_${type.replace(/\s+/g, '_')}_${source}_${getIndexUID(bulk.uid)}`; +} - return `stapps_${out}_${source}_${getIndexUID(bulk.uid)}`; +/** + * Returns an index that matches all indices with the specified type + */ +export function matchIndexByType(type: SCThingType, source: string) { + return `stapps_${type.replace(/\s+/g, '_')}_${source}_*`; } /** diff --git a/test/storage/elasticsearch/elasticsearch.spec.ts b/test/storage/elasticsearch/elasticsearch.spec.ts index 1b736c22..ab981df7 100644 --- a/test/storage/elasticsearch/elasticsearch.spec.ts +++ b/test/storage/elasticsearch/elasticsearch.spec.ts @@ -37,8 +37,13 @@ import {Logger} from '@openstapps/logger'; import {SMTP} from '@openstapps/logger/lib/smtp'; import {expect, use} from 'chai'; import chaiAsPromised from 'chai-as-promised'; +import {beforeEach} from 'mocha'; import mockedEnv from 'mocked-env'; -import {ALL_INDICES_QUERY, parseIndexName} from '../../../src/storage/elasticsearch/util'; +import { + ACTIVE_INDICES_ALIAS, + INACTIVE_INDICES_ALIAS, + parseIndexName, +} from '../../../src/storage/elasticsearch/util'; import * as queryModule from '../../../src/storage/elasticsearch/query/query'; import * as sortModule from '../../../src/storage/elasticsearch/query/sort'; import sinon, {SinonStub} from 'sinon'; @@ -287,7 +292,6 @@ describe('Elasticsearch', function () { let deleteStub: SinonStub; let refreshStub: SinonStub; let updateAliasesStub: SinonStub; - let existsStub: SinonStub; const oldIndex = 'stapps_footype_foosource_oldindex'; beforeEach(function () { @@ -297,7 +301,6 @@ describe('Elasticsearch', function () { sandbox.stub(Indices.prototype, 'putTemplate').resolves({} as any); createStub = sandbox.stub(Indices.prototype, 'create').resolves({} as any); deleteStub = sandbox.stub(Indices.prototype, 'delete').resolves({} as any); - existsStub = sandbox.stub(Indices.prototype, 'exists').resolves({} as any); refreshStub = sandbox.stub(Indices.prototype, 'refresh').resolves({} as any); updateAliasesStub = sandbox.stub(Indices.prototype, 'updateAliases').resolves({} as any); es = new Elasticsearch(configFile); @@ -329,7 +332,7 @@ describe('Elasticsearch', function () { await es.bulkCreated(bulk); expect(putTemplateStub.called).to.be.true; - expect(createStub.calledWith({index})).to.be.true; + expect(createStub.calledWith({index, aliases: {[INACTIVE_INDICES_ALIAS]: {}}})).to.be.true; }); }); @@ -341,6 +344,7 @@ describe('Elasticsearch', function () { it('should cleanup index in case of the expired bulk for bulk whose index is not in use', async function () { sandbox.stub(utilModule, 'getThingIndexName').returns(getIndex()); + await es.init(); await es.bulkExpired({...bulk, state: 'in progress'}); expect(deleteStub.called).to.be.true; @@ -349,6 +353,7 @@ describe('Elasticsearch', function () { it('should not cleanup index in case of the expired bulk for bulk whose index is in use', async function () { sandbox.stub(utilModule, 'getThingIndexName').returns(getIndex()); + await es.init(); await es.bulkExpired({...bulk, state: 'done'}); expect(deleteStub.called).to.be.false; @@ -368,44 +373,44 @@ describe('Elasticsearch', function () { return expect(es.bulkUpdated(bulk)).to.be.rejectedWith('Index'); }); - it("should create templates if index doesn't exist", async function () { + it("should refuse to finalize bulk if index doesn't exist", async function () { await es.init(); - existsStub.resolves(false); - const putTemplateSpy = sandbox.spy(templating, 'putTemplate'); - await es.bulkUpdated(bulk); + refreshStub.throws(); + await expect(es.bulkUpdated(bulk)).to.eventually.throw; - expect(createStub.called).to.be.true; - expect(putTemplateSpy.called).to.be.true; + expect( + refreshStub.calledWith({ + index: getThingIndexName(bulk.type, bulk.source, bulk), + allow_no_indices: false, + }), + ).to.be.true; }); it('should create a new index', async function () { const index = getIndex(); const expectedRefreshActions = [ { - add: {index: index, alias: SCThingType.Book}, + add: {index: index, alias: ACTIVE_INDICES_ALIAS}, }, { - remove: {index: oldIndex, alias: SCThingType.Book}, + remove: {index: index, alias: INACTIVE_INDICES_ALIAS}, + }, + { + remove_index: {index: oldIndex}, }, ]; sandbox.stub(utilModule, 'getThingIndexName').returns(index); - sandbox.stub(es, 'aliasMap').value({ - [SCThingType.Book]: { - [bulk.source]: oldIndex, - }, - }); sandbox.stub(templating, 'putTemplate'); await es.init(); await es.bulkUpdated(bulk); - expect(refreshStub.calledWith({index})).to.be.true; + expect(refreshStub.calledWith({index, allow_no_indices: false})).to.be.true; expect( updateAliasesStub.calledWith({ actions: expectedRefreshActions, }), ).to.be.true; - expect(deleteStub.called).to.be.true; }); }); }); @@ -449,6 +454,10 @@ describe('Elasticsearch', function () { es = new Elasticsearch(configFile); }); + beforeEach(function () { + sandbox.stub(Indices.prototype, 'getAlias').resolves({} as any); + }); + afterEach(function () { sandbox.restore(); }); @@ -459,33 +468,20 @@ describe('Elasticsearch', function () { const object: SearchHit = { _id: '', _index: oldIndex, - _score: 0, _source: message as SCMessage, }; - sandbox.stub(es.client, 'search').resolves(searchResponse(object)); + sandbox.stub(es.client, 'search').resolves(searchResponse(object)); sandbox.stub(utilModule, 'getThingIndexName').returns(index); - return expect(es.post(object._source!, bulk)).to.rejectedWith('exist'); - }); - - it('should not reject if the object already exists but in an index which will be rolled over', async function () { - const object: SearchHit = { - _id: '', - _index: getIndex(), - _score: 0, - _source: message as SCMessage, - }; - sandbox.stub(es.client, 'search').resolves(searchResponse(object)); - // return index name with different generated UID (see getIndex method) - sandbox.stub(utilModule, 'getThingIndexName').returns(getIndex()); - - return expect(es.post(object._source!, bulk)).to.not.rejectedWith('exist'); + await es.init(); + return expect(es.post(object._source!, bulk)).to.be.rejectedWith('UID conflict'); }); it('should reject if there is an object creation error on the elasticsearch side', async function () { sandbox.stub(es.client, 'search').resolves(searchResponse()); sandbox.stub(es.client, 'create').resolves({result: 'not_found'} as CreateResponse); + await es.init(); return expect(es.post(message as SCMessage, bulk)).to.rejectedWith('creation'); }); @@ -498,6 +494,7 @@ describe('Elasticsearch', function () { return Promise.resolve({result: 'created'}); }); + await es.init(); await es.post(message as SCMessage, bulk); expect(createStub.called).to.be.true; @@ -684,7 +681,7 @@ describe('Elasticsearch', function () { query: fakeResponse, sort: fakeBuildSortResponse, from: parameters.from, - index: ALL_INDICES_QUERY, + index: ACTIVE_INDICES_ALIAS, size: parameters.size, }); }); From be1774b1cde43b68da811bba24283f59935254e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thea=20Sch=C3=B6bl?= Date: Wed, 31 May 2023 13:54:58 +0200 Subject: [PATCH 2/2] refactor: move backend to monorepo --- .dockerignore => backend/backend/.dockerignore | 0 .editorconfig => backend/backend/.editorconfig | 0 .eslintignore => backend/backend/.eslintignore | 0 .eslintrc.json => backend/backend/.eslintrc.json | 0 .gitattributes => backend/backend/.gitattributes | 0 .gitignore => backend/backend/.gitignore | 0 .gitlab-ci.yml => backend/backend/.gitlab-ci.yml | 0 {.gitlab => backend/backend/.gitlab}/ci/getRegistryBranch.sh | 0 {.gitlab => backend/backend/.gitlab}/ci/getRegistryTag.sh | 0 {.gitlab => backend/backend/.gitlab}/ci/pushAsLatestVersion.sh | 0 {.gitlab => backend/backend/.gitlab}/ci/testCIScripts.sh | 0 {.gitlab => backend/backend/.gitlab}/issue_templates/bug.md | 0 {.gitlab => backend/backend/.gitlab}/issue_templates/feature.md | 0 .mock-yeah => backend/backend/.mock-yeah | 0 .npmignore => backend/backend/.npmignore | 0 CHANGELOG.md => backend/backend/CHANGELOG.md | 0 Dockerfile => backend/backend/Dockerfile | 0 LICENSE => backend/backend/LICENSE | 0 README.md => backend/backend/README.md | 0 ROUTES.md => backend/backend/ROUTES.md | 0 {config => backend/backend/config}/default-b-tu.ts | 0 {config => backend/backend/config}/default-f-u.ts | 0 {config => backend/backend/config}/default-fb-fh.ts | 0 {config => backend/backend/config}/default-ks-ug.ts | 0 {config => backend/backend/config}/default.ts | 0 {config => backend/backend/config}/elasticsearch-b-tu.ts | 0 {config => backend/backend/config}/elasticsearch.ts | 0 {config => backend/backend/config}/prometheus.json | 0 integration-test.yml => backend/backend/integration-test.yml | 0 package-lock.json => backend/backend/package-lock.json | 0 package.json => backend/backend/package.json | 0 {src => backend/backend/src}/app.ts | 0 {src => backend/backend/src}/cli.ts | 0 {src => backend/backend/src}/common.ts | 0 {src => backend/backend/src}/middleware/prometheus.ts | 0 {src => backend/backend/src}/notification/backend-transport.ts | 0 {src => backend/backend/src}/notification/mail-queue.ts | 0 {src => backend/backend/src}/routes/bulk-add-route.ts | 0 {src => backend/backend/src}/routes/bulk-done-route.ts | 0 {src => backend/backend/src}/routes/bulk-route.ts | 0 {src => backend/backend/src}/routes/http-types.ts | 0 {src => backend/backend/src}/routes/index-route.ts | 0 {src => backend/backend/src}/routes/multi-search-route.ts | 0 {src => backend/backend/src}/routes/plugin-register-route.ts | 0 {src => backend/backend/src}/routes/route.ts | 0 {src => backend/backend/src}/routes/search-route.ts | 0 {src => backend/backend/src}/routes/thing-update-route.ts | 0 {src => backend/backend/src}/routes/virtual-plugin-route.ts | 0 {src => backend/backend/src}/storage/bulk-storage.ts | 0 {src => backend/backend/src}/storage/database.ts | 0 .../backend/src}/storage/elasticsearch/aggregations.ts | 0 .../backend/src}/storage/elasticsearch/elasticsearch.ts | 0 {src => backend/backend/src}/storage/elasticsearch/monitoring.ts | 0 .../src}/storage/elasticsearch/query/boost/boost-functions.ts | 0 .../src}/storage/elasticsearch/query/boost/scoring-functions.ts | 0 .../backend/src}/storage/elasticsearch/query/filter.ts | 0 .../src}/storage/elasticsearch/query/filters/availability.ts | 0 .../backend/src}/storage/elasticsearch/query/filters/boolean.ts | 0 .../src}/storage/elasticsearch/query/filters/date-range.ts | 0 .../backend/src}/storage/elasticsearch/query/filters/distance.ts | 0 .../backend/src}/storage/elasticsearch/query/filters/geo.ts | 0 .../src}/storage/elasticsearch/query/filters/numeric-range.ts | 0 .../backend/src}/storage/elasticsearch/query/filters/value.ts | 0 {src => backend/backend/src}/storage/elasticsearch/query/query.ts | 0 {src => backend/backend/src}/storage/elasticsearch/query/sort.ts | 0 .../backend/src}/storage/elasticsearch/query/sort/distance.ts | 0 .../backend/src}/storage/elasticsearch/query/sort/ducet.ts | 0 .../backend/src}/storage/elasticsearch/query/sort/generic.ts | 0 .../backend/src}/storage/elasticsearch/query/sort/price.ts | 0 {src => backend/backend/src}/storage/elasticsearch/templating.ts | 0 .../src}/storage/elasticsearch/types/elasticsearch-config.ts | 0 {src => backend/backend/src}/storage/elasticsearch/types/util.ts | 0 {src => backend/backend/src}/storage/elasticsearch/util/alias.ts | 0 {src => backend/backend/src}/storage/elasticsearch/util/index.ts | 0 .../backend/src}/storage/elasticsearch/util/no-undefined.ts | 0 {src => backend/backend/src}/storage/elasticsearch/util/retry.ts | 0 {test => backend/backend/test}/app.spec.ts | 0 {test => backend/backend/test}/common.spec.ts | 0 {test => backend/backend/test}/common.ts | 0 .../backend/test}/notification/backend-transport.spec.ts | 0 {test => backend/backend/test}/notification/mail-queue.spec.ts | 0 {test => backend/backend/test}/routes/bulk-route.spec.ts | 0 {test => backend/backend/test}/routes/http-types.spec.ts | 0 {test => backend/backend/test}/routes/index-route.spec.ts | 0 .../backend/test}/routes/plugin-register-route.spec.ts | 0 {test => backend/backend/test}/routes/route.spec.ts | 0 {test => backend/backend/test}/routes/search-route.spec.ts | 0 {test => backend/backend/test}/routes/thing-update-route.spec.ts | 0 .../backend/test}/routes/virtual-plugin-route.spec.ts | 0 {test => backend/backend/test}/storage/bulk-storage.spec.ts | 0 .../backend/test}/storage/elasticsearch/aggregations.spec.ts | 0 .../backend/test}/storage/elasticsearch/elasticsearch.spec.ts | 0 .../backend/test}/storage/elasticsearch/monitoring.spec.ts | 0 .../backend/test}/storage/elasticsearch/query.spec.ts | 0 {test => backend/backend/test}/tests-setup.ts | 0 tsconfig.json => backend/backend/tsconfig.json | 0 96 files changed, 0 insertions(+), 0 deletions(-) rename .dockerignore => backend/backend/.dockerignore (100%) rename .editorconfig => backend/backend/.editorconfig (100%) rename .eslintignore => backend/backend/.eslintignore (100%) rename .eslintrc.json => backend/backend/.eslintrc.json (100%) rename .gitattributes => backend/backend/.gitattributes (100%) rename .gitignore => backend/backend/.gitignore (100%) rename .gitlab-ci.yml => backend/backend/.gitlab-ci.yml (100%) rename {.gitlab => backend/backend/.gitlab}/ci/getRegistryBranch.sh (100%) rename {.gitlab => backend/backend/.gitlab}/ci/getRegistryTag.sh (100%) rename {.gitlab => backend/backend/.gitlab}/ci/pushAsLatestVersion.sh (100%) rename {.gitlab => backend/backend/.gitlab}/ci/testCIScripts.sh (100%) rename {.gitlab => backend/backend/.gitlab}/issue_templates/bug.md (100%) rename {.gitlab => backend/backend/.gitlab}/issue_templates/feature.md (100%) rename .mock-yeah => backend/backend/.mock-yeah (100%) rename .npmignore => backend/backend/.npmignore (100%) rename CHANGELOG.md => backend/backend/CHANGELOG.md (100%) rename Dockerfile => backend/backend/Dockerfile (100%) rename LICENSE => backend/backend/LICENSE (100%) rename README.md => backend/backend/README.md (100%) rename ROUTES.md => backend/backend/ROUTES.md (100%) rename {config => backend/backend/config}/default-b-tu.ts (100%) rename {config => backend/backend/config}/default-f-u.ts (100%) rename {config => backend/backend/config}/default-fb-fh.ts (100%) rename {config => backend/backend/config}/default-ks-ug.ts (100%) rename {config => backend/backend/config}/default.ts (100%) rename {config => backend/backend/config}/elasticsearch-b-tu.ts (100%) rename {config => backend/backend/config}/elasticsearch.ts (100%) rename {config => backend/backend/config}/prometheus.json (100%) rename integration-test.yml => backend/backend/integration-test.yml (100%) rename package-lock.json => backend/backend/package-lock.json (100%) rename package.json => backend/backend/package.json (100%) rename {src => backend/backend/src}/app.ts (100%) rename {src => backend/backend/src}/cli.ts (100%) rename {src => backend/backend/src}/common.ts (100%) rename {src => backend/backend/src}/middleware/prometheus.ts (100%) rename {src => backend/backend/src}/notification/backend-transport.ts (100%) rename {src => backend/backend/src}/notification/mail-queue.ts (100%) rename {src => backend/backend/src}/routes/bulk-add-route.ts (100%) rename {src => backend/backend/src}/routes/bulk-done-route.ts (100%) rename {src => backend/backend/src}/routes/bulk-route.ts (100%) rename {src => backend/backend/src}/routes/http-types.ts (100%) rename {src => backend/backend/src}/routes/index-route.ts (100%) rename {src => backend/backend/src}/routes/multi-search-route.ts (100%) rename {src => backend/backend/src}/routes/plugin-register-route.ts (100%) rename {src => backend/backend/src}/routes/route.ts (100%) rename {src => backend/backend/src}/routes/search-route.ts (100%) rename {src => backend/backend/src}/routes/thing-update-route.ts (100%) rename {src => backend/backend/src}/routes/virtual-plugin-route.ts (100%) rename {src => backend/backend/src}/storage/bulk-storage.ts (100%) rename {src => backend/backend/src}/storage/database.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/aggregations.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/elasticsearch.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/monitoring.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/boost/boost-functions.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/boost/scoring-functions.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/filter.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/filters/availability.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/filters/boolean.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/filters/date-range.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/filters/distance.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/filters/geo.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/filters/numeric-range.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/filters/value.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/query.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/sort.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/sort/distance.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/sort/ducet.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/sort/generic.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/query/sort/price.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/templating.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/types/elasticsearch-config.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/types/util.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/util/alias.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/util/index.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/util/no-undefined.ts (100%) rename {src => backend/backend/src}/storage/elasticsearch/util/retry.ts (100%) rename {test => backend/backend/test}/app.spec.ts (100%) rename {test => backend/backend/test}/common.spec.ts (100%) rename {test => backend/backend/test}/common.ts (100%) rename {test => backend/backend/test}/notification/backend-transport.spec.ts (100%) rename {test => backend/backend/test}/notification/mail-queue.spec.ts (100%) rename {test => backend/backend/test}/routes/bulk-route.spec.ts (100%) rename {test => backend/backend/test}/routes/http-types.spec.ts (100%) rename {test => backend/backend/test}/routes/index-route.spec.ts (100%) rename {test => backend/backend/test}/routes/plugin-register-route.spec.ts (100%) rename {test => backend/backend/test}/routes/route.spec.ts (100%) rename {test => backend/backend/test}/routes/search-route.spec.ts (100%) rename {test => backend/backend/test}/routes/thing-update-route.spec.ts (100%) rename {test => backend/backend/test}/routes/virtual-plugin-route.spec.ts (100%) rename {test => backend/backend/test}/storage/bulk-storage.spec.ts (100%) rename {test => backend/backend/test}/storage/elasticsearch/aggregations.spec.ts (100%) rename {test => backend/backend/test}/storage/elasticsearch/elasticsearch.spec.ts (100%) rename {test => backend/backend/test}/storage/elasticsearch/monitoring.spec.ts (100%) rename {test => backend/backend/test}/storage/elasticsearch/query.spec.ts (100%) rename {test => backend/backend/test}/tests-setup.ts (100%) rename tsconfig.json => backend/backend/tsconfig.json (100%) diff --git a/.dockerignore b/backend/backend/.dockerignore similarity index 100% rename from .dockerignore rename to backend/backend/.dockerignore diff --git a/.editorconfig b/backend/backend/.editorconfig similarity index 100% rename from .editorconfig rename to backend/backend/.editorconfig diff --git a/.eslintignore b/backend/backend/.eslintignore similarity index 100% rename from .eslintignore rename to backend/backend/.eslintignore diff --git a/.eslintrc.json b/backend/backend/.eslintrc.json similarity index 100% rename from .eslintrc.json rename to backend/backend/.eslintrc.json diff --git a/.gitattributes b/backend/backend/.gitattributes similarity index 100% rename from .gitattributes rename to backend/backend/.gitattributes diff --git a/.gitignore b/backend/backend/.gitignore similarity index 100% rename from .gitignore rename to backend/backend/.gitignore diff --git a/.gitlab-ci.yml b/backend/backend/.gitlab-ci.yml similarity index 100% rename from .gitlab-ci.yml rename to backend/backend/.gitlab-ci.yml diff --git a/.gitlab/ci/getRegistryBranch.sh b/backend/backend/.gitlab/ci/getRegistryBranch.sh similarity index 100% rename from .gitlab/ci/getRegistryBranch.sh rename to backend/backend/.gitlab/ci/getRegistryBranch.sh diff --git a/.gitlab/ci/getRegistryTag.sh b/backend/backend/.gitlab/ci/getRegistryTag.sh similarity index 100% rename from .gitlab/ci/getRegistryTag.sh rename to backend/backend/.gitlab/ci/getRegistryTag.sh diff --git a/.gitlab/ci/pushAsLatestVersion.sh b/backend/backend/.gitlab/ci/pushAsLatestVersion.sh similarity index 100% rename from .gitlab/ci/pushAsLatestVersion.sh rename to backend/backend/.gitlab/ci/pushAsLatestVersion.sh diff --git a/.gitlab/ci/testCIScripts.sh b/backend/backend/.gitlab/ci/testCIScripts.sh similarity index 100% rename from .gitlab/ci/testCIScripts.sh rename to backend/backend/.gitlab/ci/testCIScripts.sh diff --git a/.gitlab/issue_templates/bug.md b/backend/backend/.gitlab/issue_templates/bug.md similarity index 100% rename from .gitlab/issue_templates/bug.md rename to backend/backend/.gitlab/issue_templates/bug.md diff --git a/.gitlab/issue_templates/feature.md b/backend/backend/.gitlab/issue_templates/feature.md similarity index 100% rename from .gitlab/issue_templates/feature.md rename to backend/backend/.gitlab/issue_templates/feature.md diff --git a/.mock-yeah b/backend/backend/.mock-yeah similarity index 100% rename from .mock-yeah rename to backend/backend/.mock-yeah diff --git a/.npmignore b/backend/backend/.npmignore similarity index 100% rename from .npmignore rename to backend/backend/.npmignore diff --git a/CHANGELOG.md b/backend/backend/CHANGELOG.md similarity index 100% rename from CHANGELOG.md rename to backend/backend/CHANGELOG.md diff --git a/Dockerfile b/backend/backend/Dockerfile similarity index 100% rename from Dockerfile rename to backend/backend/Dockerfile diff --git a/LICENSE b/backend/backend/LICENSE similarity index 100% rename from LICENSE rename to backend/backend/LICENSE diff --git a/README.md b/backend/backend/README.md similarity index 100% rename from README.md rename to backend/backend/README.md diff --git a/ROUTES.md b/backend/backend/ROUTES.md similarity index 100% rename from ROUTES.md rename to backend/backend/ROUTES.md diff --git a/config/default-b-tu.ts b/backend/backend/config/default-b-tu.ts similarity index 100% rename from config/default-b-tu.ts rename to backend/backend/config/default-b-tu.ts diff --git a/config/default-f-u.ts b/backend/backend/config/default-f-u.ts similarity index 100% rename from config/default-f-u.ts rename to backend/backend/config/default-f-u.ts diff --git a/config/default-fb-fh.ts b/backend/backend/config/default-fb-fh.ts similarity index 100% rename from config/default-fb-fh.ts rename to backend/backend/config/default-fb-fh.ts diff --git a/config/default-ks-ug.ts b/backend/backend/config/default-ks-ug.ts similarity index 100% rename from config/default-ks-ug.ts rename to backend/backend/config/default-ks-ug.ts diff --git a/config/default.ts b/backend/backend/config/default.ts similarity index 100% rename from config/default.ts rename to backend/backend/config/default.ts diff --git a/config/elasticsearch-b-tu.ts b/backend/backend/config/elasticsearch-b-tu.ts similarity index 100% rename from config/elasticsearch-b-tu.ts rename to backend/backend/config/elasticsearch-b-tu.ts diff --git a/config/elasticsearch.ts b/backend/backend/config/elasticsearch.ts similarity index 100% rename from config/elasticsearch.ts rename to backend/backend/config/elasticsearch.ts diff --git a/config/prometheus.json b/backend/backend/config/prometheus.json similarity index 100% rename from config/prometheus.json rename to backend/backend/config/prometheus.json diff --git a/integration-test.yml b/backend/backend/integration-test.yml similarity index 100% rename from integration-test.yml rename to backend/backend/integration-test.yml diff --git a/package-lock.json b/backend/backend/package-lock.json similarity index 100% rename from package-lock.json rename to backend/backend/package-lock.json diff --git a/package.json b/backend/backend/package.json similarity index 100% rename from package.json rename to backend/backend/package.json diff --git a/src/app.ts b/backend/backend/src/app.ts similarity index 100% rename from src/app.ts rename to backend/backend/src/app.ts diff --git a/src/cli.ts b/backend/backend/src/cli.ts similarity index 100% rename from src/cli.ts rename to backend/backend/src/cli.ts diff --git a/src/common.ts b/backend/backend/src/common.ts similarity index 100% rename from src/common.ts rename to backend/backend/src/common.ts diff --git a/src/middleware/prometheus.ts b/backend/backend/src/middleware/prometheus.ts similarity index 100% rename from src/middleware/prometheus.ts rename to backend/backend/src/middleware/prometheus.ts diff --git a/src/notification/backend-transport.ts b/backend/backend/src/notification/backend-transport.ts similarity index 100% rename from src/notification/backend-transport.ts rename to backend/backend/src/notification/backend-transport.ts diff --git a/src/notification/mail-queue.ts b/backend/backend/src/notification/mail-queue.ts similarity index 100% rename from src/notification/mail-queue.ts rename to backend/backend/src/notification/mail-queue.ts diff --git a/src/routes/bulk-add-route.ts b/backend/backend/src/routes/bulk-add-route.ts similarity index 100% rename from src/routes/bulk-add-route.ts rename to backend/backend/src/routes/bulk-add-route.ts diff --git a/src/routes/bulk-done-route.ts b/backend/backend/src/routes/bulk-done-route.ts similarity index 100% rename from src/routes/bulk-done-route.ts rename to backend/backend/src/routes/bulk-done-route.ts diff --git a/src/routes/bulk-route.ts b/backend/backend/src/routes/bulk-route.ts similarity index 100% rename from src/routes/bulk-route.ts rename to backend/backend/src/routes/bulk-route.ts diff --git a/src/routes/http-types.ts b/backend/backend/src/routes/http-types.ts similarity index 100% rename from src/routes/http-types.ts rename to backend/backend/src/routes/http-types.ts diff --git a/src/routes/index-route.ts b/backend/backend/src/routes/index-route.ts similarity index 100% rename from src/routes/index-route.ts rename to backend/backend/src/routes/index-route.ts diff --git a/src/routes/multi-search-route.ts b/backend/backend/src/routes/multi-search-route.ts similarity index 100% rename from src/routes/multi-search-route.ts rename to backend/backend/src/routes/multi-search-route.ts diff --git a/src/routes/plugin-register-route.ts b/backend/backend/src/routes/plugin-register-route.ts similarity index 100% rename from src/routes/plugin-register-route.ts rename to backend/backend/src/routes/plugin-register-route.ts diff --git a/src/routes/route.ts b/backend/backend/src/routes/route.ts similarity index 100% rename from src/routes/route.ts rename to backend/backend/src/routes/route.ts diff --git a/src/routes/search-route.ts b/backend/backend/src/routes/search-route.ts similarity index 100% rename from src/routes/search-route.ts rename to backend/backend/src/routes/search-route.ts diff --git a/src/routes/thing-update-route.ts b/backend/backend/src/routes/thing-update-route.ts similarity index 100% rename from src/routes/thing-update-route.ts rename to backend/backend/src/routes/thing-update-route.ts diff --git a/src/routes/virtual-plugin-route.ts b/backend/backend/src/routes/virtual-plugin-route.ts similarity index 100% rename from src/routes/virtual-plugin-route.ts rename to backend/backend/src/routes/virtual-plugin-route.ts diff --git a/src/storage/bulk-storage.ts b/backend/backend/src/storage/bulk-storage.ts similarity index 100% rename from src/storage/bulk-storage.ts rename to backend/backend/src/storage/bulk-storage.ts diff --git a/src/storage/database.ts b/backend/backend/src/storage/database.ts similarity index 100% rename from src/storage/database.ts rename to backend/backend/src/storage/database.ts diff --git a/src/storage/elasticsearch/aggregations.ts b/backend/backend/src/storage/elasticsearch/aggregations.ts similarity index 100% rename from src/storage/elasticsearch/aggregations.ts rename to backend/backend/src/storage/elasticsearch/aggregations.ts diff --git a/src/storage/elasticsearch/elasticsearch.ts b/backend/backend/src/storage/elasticsearch/elasticsearch.ts similarity index 100% rename from src/storage/elasticsearch/elasticsearch.ts rename to backend/backend/src/storage/elasticsearch/elasticsearch.ts diff --git a/src/storage/elasticsearch/monitoring.ts b/backend/backend/src/storage/elasticsearch/monitoring.ts similarity index 100% rename from src/storage/elasticsearch/monitoring.ts rename to backend/backend/src/storage/elasticsearch/monitoring.ts diff --git a/src/storage/elasticsearch/query/boost/boost-functions.ts b/backend/backend/src/storage/elasticsearch/query/boost/boost-functions.ts similarity index 100% rename from src/storage/elasticsearch/query/boost/boost-functions.ts rename to backend/backend/src/storage/elasticsearch/query/boost/boost-functions.ts diff --git a/src/storage/elasticsearch/query/boost/scoring-functions.ts b/backend/backend/src/storage/elasticsearch/query/boost/scoring-functions.ts similarity index 100% rename from src/storage/elasticsearch/query/boost/scoring-functions.ts rename to backend/backend/src/storage/elasticsearch/query/boost/scoring-functions.ts diff --git a/src/storage/elasticsearch/query/filter.ts b/backend/backend/src/storage/elasticsearch/query/filter.ts similarity index 100% rename from src/storage/elasticsearch/query/filter.ts rename to backend/backend/src/storage/elasticsearch/query/filter.ts diff --git a/src/storage/elasticsearch/query/filters/availability.ts b/backend/backend/src/storage/elasticsearch/query/filters/availability.ts similarity index 100% rename from src/storage/elasticsearch/query/filters/availability.ts rename to backend/backend/src/storage/elasticsearch/query/filters/availability.ts diff --git a/src/storage/elasticsearch/query/filters/boolean.ts b/backend/backend/src/storage/elasticsearch/query/filters/boolean.ts similarity index 100% rename from src/storage/elasticsearch/query/filters/boolean.ts rename to backend/backend/src/storage/elasticsearch/query/filters/boolean.ts diff --git a/src/storage/elasticsearch/query/filters/date-range.ts b/backend/backend/src/storage/elasticsearch/query/filters/date-range.ts similarity index 100% rename from src/storage/elasticsearch/query/filters/date-range.ts rename to backend/backend/src/storage/elasticsearch/query/filters/date-range.ts diff --git a/src/storage/elasticsearch/query/filters/distance.ts b/backend/backend/src/storage/elasticsearch/query/filters/distance.ts similarity index 100% rename from src/storage/elasticsearch/query/filters/distance.ts rename to backend/backend/src/storage/elasticsearch/query/filters/distance.ts diff --git a/src/storage/elasticsearch/query/filters/geo.ts b/backend/backend/src/storage/elasticsearch/query/filters/geo.ts similarity index 100% rename from src/storage/elasticsearch/query/filters/geo.ts rename to backend/backend/src/storage/elasticsearch/query/filters/geo.ts diff --git a/src/storage/elasticsearch/query/filters/numeric-range.ts b/backend/backend/src/storage/elasticsearch/query/filters/numeric-range.ts similarity index 100% rename from src/storage/elasticsearch/query/filters/numeric-range.ts rename to backend/backend/src/storage/elasticsearch/query/filters/numeric-range.ts diff --git a/src/storage/elasticsearch/query/filters/value.ts b/backend/backend/src/storage/elasticsearch/query/filters/value.ts similarity index 100% rename from src/storage/elasticsearch/query/filters/value.ts rename to backend/backend/src/storage/elasticsearch/query/filters/value.ts diff --git a/src/storage/elasticsearch/query/query.ts b/backend/backend/src/storage/elasticsearch/query/query.ts similarity index 100% rename from src/storage/elasticsearch/query/query.ts rename to backend/backend/src/storage/elasticsearch/query/query.ts diff --git a/src/storage/elasticsearch/query/sort.ts b/backend/backend/src/storage/elasticsearch/query/sort.ts similarity index 100% rename from src/storage/elasticsearch/query/sort.ts rename to backend/backend/src/storage/elasticsearch/query/sort.ts diff --git a/src/storage/elasticsearch/query/sort/distance.ts b/backend/backend/src/storage/elasticsearch/query/sort/distance.ts similarity index 100% rename from src/storage/elasticsearch/query/sort/distance.ts rename to backend/backend/src/storage/elasticsearch/query/sort/distance.ts diff --git a/src/storage/elasticsearch/query/sort/ducet.ts b/backend/backend/src/storage/elasticsearch/query/sort/ducet.ts similarity index 100% rename from src/storage/elasticsearch/query/sort/ducet.ts rename to backend/backend/src/storage/elasticsearch/query/sort/ducet.ts diff --git a/src/storage/elasticsearch/query/sort/generic.ts b/backend/backend/src/storage/elasticsearch/query/sort/generic.ts similarity index 100% rename from src/storage/elasticsearch/query/sort/generic.ts rename to backend/backend/src/storage/elasticsearch/query/sort/generic.ts diff --git a/src/storage/elasticsearch/query/sort/price.ts b/backend/backend/src/storage/elasticsearch/query/sort/price.ts similarity index 100% rename from src/storage/elasticsearch/query/sort/price.ts rename to backend/backend/src/storage/elasticsearch/query/sort/price.ts diff --git a/src/storage/elasticsearch/templating.ts b/backend/backend/src/storage/elasticsearch/templating.ts similarity index 100% rename from src/storage/elasticsearch/templating.ts rename to backend/backend/src/storage/elasticsearch/templating.ts diff --git a/src/storage/elasticsearch/types/elasticsearch-config.ts b/backend/backend/src/storage/elasticsearch/types/elasticsearch-config.ts similarity index 100% rename from src/storage/elasticsearch/types/elasticsearch-config.ts rename to backend/backend/src/storage/elasticsearch/types/elasticsearch-config.ts diff --git a/src/storage/elasticsearch/types/util.ts b/backend/backend/src/storage/elasticsearch/types/util.ts similarity index 100% rename from src/storage/elasticsearch/types/util.ts rename to backend/backend/src/storage/elasticsearch/types/util.ts diff --git a/src/storage/elasticsearch/util/alias.ts b/backend/backend/src/storage/elasticsearch/util/alias.ts similarity index 100% rename from src/storage/elasticsearch/util/alias.ts rename to backend/backend/src/storage/elasticsearch/util/alias.ts diff --git a/src/storage/elasticsearch/util/index.ts b/backend/backend/src/storage/elasticsearch/util/index.ts similarity index 100% rename from src/storage/elasticsearch/util/index.ts rename to backend/backend/src/storage/elasticsearch/util/index.ts diff --git a/src/storage/elasticsearch/util/no-undefined.ts b/backend/backend/src/storage/elasticsearch/util/no-undefined.ts similarity index 100% rename from src/storage/elasticsearch/util/no-undefined.ts rename to backend/backend/src/storage/elasticsearch/util/no-undefined.ts diff --git a/src/storage/elasticsearch/util/retry.ts b/backend/backend/src/storage/elasticsearch/util/retry.ts similarity index 100% rename from src/storage/elasticsearch/util/retry.ts rename to backend/backend/src/storage/elasticsearch/util/retry.ts diff --git a/test/app.spec.ts b/backend/backend/test/app.spec.ts similarity index 100% rename from test/app.spec.ts rename to backend/backend/test/app.spec.ts diff --git a/test/common.spec.ts b/backend/backend/test/common.spec.ts similarity index 100% rename from test/common.spec.ts rename to backend/backend/test/common.spec.ts diff --git a/test/common.ts b/backend/backend/test/common.ts similarity index 100% rename from test/common.ts rename to backend/backend/test/common.ts diff --git a/test/notification/backend-transport.spec.ts b/backend/backend/test/notification/backend-transport.spec.ts similarity index 100% rename from test/notification/backend-transport.spec.ts rename to backend/backend/test/notification/backend-transport.spec.ts diff --git a/test/notification/mail-queue.spec.ts b/backend/backend/test/notification/mail-queue.spec.ts similarity index 100% rename from test/notification/mail-queue.spec.ts rename to backend/backend/test/notification/mail-queue.spec.ts diff --git a/test/routes/bulk-route.spec.ts b/backend/backend/test/routes/bulk-route.spec.ts similarity index 100% rename from test/routes/bulk-route.spec.ts rename to backend/backend/test/routes/bulk-route.spec.ts diff --git a/test/routes/http-types.spec.ts b/backend/backend/test/routes/http-types.spec.ts similarity index 100% rename from test/routes/http-types.spec.ts rename to backend/backend/test/routes/http-types.spec.ts diff --git a/test/routes/index-route.spec.ts b/backend/backend/test/routes/index-route.spec.ts similarity index 100% rename from test/routes/index-route.spec.ts rename to backend/backend/test/routes/index-route.spec.ts diff --git a/test/routes/plugin-register-route.spec.ts b/backend/backend/test/routes/plugin-register-route.spec.ts similarity index 100% rename from test/routes/plugin-register-route.spec.ts rename to backend/backend/test/routes/plugin-register-route.spec.ts diff --git a/test/routes/route.spec.ts b/backend/backend/test/routes/route.spec.ts similarity index 100% rename from test/routes/route.spec.ts rename to backend/backend/test/routes/route.spec.ts diff --git a/test/routes/search-route.spec.ts b/backend/backend/test/routes/search-route.spec.ts similarity index 100% rename from test/routes/search-route.spec.ts rename to backend/backend/test/routes/search-route.spec.ts diff --git a/test/routes/thing-update-route.spec.ts b/backend/backend/test/routes/thing-update-route.spec.ts similarity index 100% rename from test/routes/thing-update-route.spec.ts rename to backend/backend/test/routes/thing-update-route.spec.ts diff --git a/test/routes/virtual-plugin-route.spec.ts b/backend/backend/test/routes/virtual-plugin-route.spec.ts similarity index 100% rename from test/routes/virtual-plugin-route.spec.ts rename to backend/backend/test/routes/virtual-plugin-route.spec.ts diff --git a/test/storage/bulk-storage.spec.ts b/backend/backend/test/storage/bulk-storage.spec.ts similarity index 100% rename from test/storage/bulk-storage.spec.ts rename to backend/backend/test/storage/bulk-storage.spec.ts diff --git a/test/storage/elasticsearch/aggregations.spec.ts b/backend/backend/test/storage/elasticsearch/aggregations.spec.ts similarity index 100% rename from test/storage/elasticsearch/aggregations.spec.ts rename to backend/backend/test/storage/elasticsearch/aggregations.spec.ts diff --git a/test/storage/elasticsearch/elasticsearch.spec.ts b/backend/backend/test/storage/elasticsearch/elasticsearch.spec.ts similarity index 100% rename from test/storage/elasticsearch/elasticsearch.spec.ts rename to backend/backend/test/storage/elasticsearch/elasticsearch.spec.ts diff --git a/test/storage/elasticsearch/monitoring.spec.ts b/backend/backend/test/storage/elasticsearch/monitoring.spec.ts similarity index 100% rename from test/storage/elasticsearch/monitoring.spec.ts rename to backend/backend/test/storage/elasticsearch/monitoring.spec.ts diff --git a/test/storage/elasticsearch/query.spec.ts b/backend/backend/test/storage/elasticsearch/query.spec.ts similarity index 100% rename from test/storage/elasticsearch/query.spec.ts rename to backend/backend/test/storage/elasticsearch/query.spec.ts diff --git a/test/tests-setup.ts b/backend/backend/test/tests-setup.ts similarity index 100% rename from test/tests-setup.ts rename to backend/backend/test/tests-setup.ts diff --git a/tsconfig.json b/backend/backend/tsconfig.json similarity index 100% rename from tsconfig.json rename to backend/backend/tsconfig.json