mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Enable prettier for saved objects (#33194)
This commit is contained in:
parent
b90241cf45
commit
2fa3c01928
18 changed files with 1912 additions and 1680 deletions
|
@ -67,6 +67,7 @@ module.exports = {
|
|||
'packages/kbn-test-subj-selector/**/*',
|
||||
'packages/kbn-test/**/*',
|
||||
'packages/kbn-eslint-import-resolver-kibana/**/*',
|
||||
'src/legacy/server/saved_objects/**/*',
|
||||
'x-pack/plugins/apm/**/*',
|
||||
'x-pack/plugins/canvas/**/*',
|
||||
],
|
||||
|
|
|
@ -20,7 +20,11 @@
|
|||
import { KibanaMigrator } from './migrations';
|
||||
import { SavedObjectsSchema } from './schema';
|
||||
import { SavedObjectsSerializer } from './serialization';
|
||||
import { SavedObjectsClient, SavedObjectsRepository, ScopedSavedObjectsClientProvider } from './service';
|
||||
import {
|
||||
SavedObjectsClient,
|
||||
SavedObjectsRepository,
|
||||
ScopedSavedObjectsClientProvider,
|
||||
} from './service';
|
||||
import { getRootPropertiesObjects } from '../mappings';
|
||||
|
||||
import {
|
||||
|
@ -41,7 +45,7 @@ export function savedObjectsMixin(kbnServer, server) {
|
|||
|
||||
server.decorate('server', 'kibanaMigrator', migrator);
|
||||
|
||||
const warn = (message) => server.log(['warning', 'saved-objects'], message);
|
||||
const warn = message => server.log(['warning', 'saved-objects'], message);
|
||||
// we use kibana.index which is technically defined in the kibana plugin, so if
|
||||
// we don't have the plugin (mainly tests) we can't initialize the saved objects
|
||||
if (!kbnServer.pluginSpecs.some(p => p.getId() === 'kibana')) {
|
||||
|
@ -75,12 +79,12 @@ export function savedObjectsMixin(kbnServer, server) {
|
|||
const visibleTypes = allTypes.filter(type => !schema.isHiddenType(type));
|
||||
|
||||
const createRepository = (callCluster, extraTypes = []) => {
|
||||
if(typeof callCluster !== 'function') {
|
||||
if (typeof callCluster !== 'function') {
|
||||
throw new TypeError('Repository requires a "callCluster" function to be provided.');
|
||||
}
|
||||
// throw an exception if an extraType is not defined.
|
||||
extraTypes.forEach(type => {
|
||||
if(!allTypes.includes(type)) {
|
||||
if (!allTypes.includes(type)) {
|
||||
throw new Error(`Missing mappings for saved objects type '${type}'`);
|
||||
}
|
||||
});
|
||||
|
@ -94,7 +98,7 @@ export function savedObjectsMixin(kbnServer, server) {
|
|||
schema,
|
||||
serializer,
|
||||
allowedTypes,
|
||||
callCluster
|
||||
callCluster,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -123,7 +127,7 @@ export function savedObjectsMixin(kbnServer, server) {
|
|||
server.decorate('server', 'savedObjects', service);
|
||||
|
||||
const savedObjectsClientCache = new WeakMap();
|
||||
server.decorate('request', 'getSavedObjectsClient', function () {
|
||||
server.decorate('request', 'getSavedObjectsClient', function() {
|
||||
const request = this;
|
||||
|
||||
if (savedObjectsClientCache.has(request)) {
|
||||
|
|
|
@ -28,7 +28,7 @@ describe('Saved Objects Mixin', () => {
|
|||
'kibana.index': 'kibana.index',
|
||||
'savedObjects.maxImportExportSize': 10000,
|
||||
};
|
||||
const stubConfig = jest.fn((key) => {
|
||||
const stubConfig = jest.fn(key => {
|
||||
return config[key];
|
||||
});
|
||||
|
||||
|
@ -57,12 +57,16 @@ describe('Saved Objects Mixin', () => {
|
|||
mockKbnServer = {
|
||||
server: mockServer,
|
||||
ready: () => {},
|
||||
pluginSpecs: { some: () => { return true; } },
|
||||
pluginSpecs: {
|
||||
some: () => {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
uiExports: {
|
||||
savedObjectSchemas: {
|
||||
hiddentype: {
|
||||
hidden: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
savedObjectMappings: [
|
||||
{
|
||||
|
@ -95,7 +99,11 @@ describe('Saved Objects Mixin', () => {
|
|||
mockKbnServer.pluginSpecs.some = () => false;
|
||||
savedObjectsMixin(mockKbnServer, mockServer);
|
||||
expect(mockServer.log).toHaveBeenCalledWith(expect.any(Array), expect.any(String));
|
||||
expect(mockServer.decorate).toHaveBeenCalledWith('server', 'kibanaMigrator', expect.any(Object));
|
||||
expect(mockServer.decorate).toHaveBeenCalledWith(
|
||||
'server',
|
||||
'kibanaMigrator',
|
||||
expect.any(Object)
|
||||
);
|
||||
expect(mockServer.decorate).toHaveBeenCalledTimes(1);
|
||||
expect(mockServer.route).not.toHaveBeenCalled();
|
||||
});
|
||||
|
@ -108,44 +116,66 @@ describe('Saved Objects Mixin', () => {
|
|||
});
|
||||
it('should add POST /api/saved_objects/_bulk_create', () => {
|
||||
savedObjectsMixin(mockKbnServer, mockServer);
|
||||
expect(mockServer.route).toHaveBeenCalledWith(expect.objectContaining({ path: '/api/saved_objects/_bulk_create', method: 'POST' }));
|
||||
expect(mockServer.route).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ path: '/api/saved_objects/_bulk_create', method: 'POST' })
|
||||
);
|
||||
});
|
||||
it('should add POST /api/saved_objects/_bulk_get', () => {
|
||||
savedObjectsMixin(mockKbnServer, mockServer);
|
||||
expect(mockServer.route).toHaveBeenCalledWith(expect.objectContaining({ path: '/api/saved_objects/_bulk_get', method: 'POST' }));
|
||||
expect(mockServer.route).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ path: '/api/saved_objects/_bulk_get', method: 'POST' })
|
||||
);
|
||||
});
|
||||
it('should add POST /api/saved_objects/{type}/{id?}', () => {
|
||||
savedObjectsMixin(mockKbnServer, mockServer);
|
||||
expect(mockServer.route).toHaveBeenCalledWith(expect.objectContaining({ path: '/api/saved_objects/{type}/{id?}', method: 'POST' }));
|
||||
expect(mockServer.route).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ path: '/api/saved_objects/{type}/{id?}', method: 'POST' })
|
||||
);
|
||||
});
|
||||
it('should add DELETE /api/saved_objects/{type}/{id}', () => {
|
||||
savedObjectsMixin(mockKbnServer, mockServer);
|
||||
expect(mockServer.route).toHaveBeenCalledWith(expect.objectContaining({ path: '/api/saved_objects/{type}/{id}', method: 'DELETE' }));
|
||||
expect(mockServer.route).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ path: '/api/saved_objects/{type}/{id}', method: 'DELETE' })
|
||||
);
|
||||
});
|
||||
it('should add GET /api/saved_objects/_find', () => {
|
||||
savedObjectsMixin(mockKbnServer, mockServer);
|
||||
expect(mockServer.route).toHaveBeenCalledWith(expect.objectContaining({ path: '/api/saved_objects/_find', method: 'GET' }));
|
||||
expect(mockServer.route).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ path: '/api/saved_objects/_find', method: 'GET' })
|
||||
);
|
||||
});
|
||||
it('should add GET /api/saved_objects/{type}/{id}', () => {
|
||||
savedObjectsMixin(mockKbnServer, mockServer);
|
||||
expect(mockServer.route).toHaveBeenCalledWith(expect.objectContaining({ path: '/api/saved_objects/{type}/{id}', method: 'GET' }));
|
||||
expect(mockServer.route).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ path: '/api/saved_objects/{type}/{id}', method: 'GET' })
|
||||
);
|
||||
});
|
||||
it('should add PUT /api/saved_objects/{type}/{id}', () => {
|
||||
savedObjectsMixin(mockKbnServer, mockServer);
|
||||
expect(mockServer.route).toHaveBeenCalledWith(expect.objectContaining({ path: '/api/saved_objects/{type}/{id}', method: 'PUT' }));
|
||||
expect(mockServer.route).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ path: '/api/saved_objects/{type}/{id}', method: 'PUT' })
|
||||
);
|
||||
});
|
||||
it('should add GET /api/saved_objects/_export', () => {
|
||||
savedObjectsMixin(mockKbnServer, mockServer);
|
||||
expect(mockServer.route).toHaveBeenCalledWith(expect.objectContaining({ path: '/api/saved_objects/_export', method: 'POST' }));
|
||||
expect(mockServer.route).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ path: '/api/saved_objects/_export', method: 'POST' })
|
||||
);
|
||||
});
|
||||
it('should add POST /api/saved_objects/_import', () => {
|
||||
savedObjectsMixin(mockKbnServer, mockServer);
|
||||
expect(mockServer.route).toHaveBeenCalledWith(expect.objectContaining({ path: '/api/saved_objects/_import', method: 'POST' }));
|
||||
expect(mockServer.route).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ path: '/api/saved_objects/_import', method: 'POST' })
|
||||
);
|
||||
});
|
||||
it('should add POST /api/saved_objects/_resolve_import_errors', () => {
|
||||
savedObjectsMixin(mockKbnServer, mockServer);
|
||||
expect(mockServer.route)
|
||||
.toHaveBeenCalledWith(expect.objectContaining({ path: '/api/saved_objects/_resolve_import_errors', method: 'POST' }));
|
||||
expect(mockServer.route).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
path: '/api/saved_objects/_resolve_import_errors',
|
||||
method: 'POST',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -154,7 +184,9 @@ describe('Saved Objects Mixin', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
savedObjectsMixin(mockKbnServer, mockServer);
|
||||
const call = mockServer.decorate.mock.calls.filter(([objName, methodName]) => objName === 'server' && methodName === 'savedObjects');
|
||||
const call = mockServer.decorate.mock.calls.filter(
|
||||
([objName, methodName]) => objName === 'server' && methodName === 'savedObjects'
|
||||
);
|
||||
service = call[0][2];
|
||||
});
|
||||
|
||||
|
@ -168,7 +200,7 @@ describe('Saved Objects Mixin', () => {
|
|||
it('should not allow a repository with an undefined type', () => {
|
||||
expect(() => {
|
||||
service.getSavedObjectsRepository(mockCallEs, ['extraType']);
|
||||
}).toThrow(new Error('Missing mappings for saved objects type \'extraType\''));
|
||||
}).toThrow(new Error("Missing mappings for saved objects type 'extraType'"));
|
||||
});
|
||||
|
||||
it('should create a repository without hidden types', () => {
|
||||
|
@ -178,12 +210,19 @@ describe('Saved Objects Mixin', () => {
|
|||
});
|
||||
|
||||
it('should create a repository with a unique list of allowed types', () => {
|
||||
const repository = service.getSavedObjectsRepository(mockCallEs, ['config', 'config', 'config']);
|
||||
const repository = service.getSavedObjectsRepository(mockCallEs, [
|
||||
'config',
|
||||
'config',
|
||||
'config',
|
||||
]);
|
||||
expect(repository._allowedTypes).toEqual(['config', 'testtype']);
|
||||
});
|
||||
|
||||
it('should create a repository with extraTypes minus duplicate', () => {
|
||||
const repository = service.getSavedObjectsRepository(mockCallEs, ['hiddentype', 'hiddentype']);
|
||||
const repository = service.getSavedObjectsRepository(mockCallEs, [
|
||||
'hiddentype',
|
||||
'hiddentype',
|
||||
]);
|
||||
expect(repository._allowedTypes).toEqual(['config', 'testtype', 'hiddentype']);
|
||||
});
|
||||
|
||||
|
@ -221,7 +260,7 @@ describe('Saved Objects Mixin', () => {
|
|||
});
|
||||
|
||||
it('should call underlining callCluster', async () => {
|
||||
stubCallCluster.mockImplementation((method) => {
|
||||
stubCallCluster.mockImplementation(method => {
|
||||
if (method === 'indices.get') {
|
||||
return { status: 404 };
|
||||
} else if (method === 'indices.getAlias') {
|
||||
|
|
|
@ -30,7 +30,7 @@ const {
|
|||
403: Forbidden,
|
||||
413: RequestEntityTooLarge,
|
||||
NotFound,
|
||||
BadRequest
|
||||
BadRequest,
|
||||
} = elasticsearch.errors;
|
||||
|
||||
import {
|
||||
|
|
|
@ -65,7 +65,6 @@ export function isInvalidVersionError(error) {
|
|||
return error && error[code] === CODE_INVALID_VERSION;
|
||||
}
|
||||
|
||||
|
||||
// 401 - Not Authorized
|
||||
const CODE_NOT_AUTHORIZED = 'SavedObjectsClient/notAuthorized';
|
||||
export function decorateNotAuthorizedError(error, reason) {
|
||||
|
@ -75,7 +74,6 @@ export function isNotAuthorizedError(error) {
|
|||
return error && error[code] === CODE_NOT_AUTHORIZED;
|
||||
}
|
||||
|
||||
|
||||
// 403 - Forbidden
|
||||
const CODE_FORBIDDEN = 'SavedObjectsClient/forbidden';
|
||||
export function decorateForbiddenError(error, reason) {
|
||||
|
@ -85,7 +83,6 @@ export function isForbiddenError(error) {
|
|||
return error && error[code] === CODE_FORBIDDEN;
|
||||
}
|
||||
|
||||
|
||||
// 413 - Request Entity Too Large
|
||||
const CODE_REQUEST_ENTITY_TOO_LARGE = 'SavedObjectsClient/requestEntityTooLarge';
|
||||
export function decorateRequestEntityTooLargeError(error, reason) {
|
||||
|
@ -95,7 +92,6 @@ export function isRequestEntityTooLargeError(error) {
|
|||
return error && error[code] === CODE_REQUEST_ENTITY_TOO_LARGE;
|
||||
}
|
||||
|
||||
|
||||
// 404 - Not Found
|
||||
const CODE_NOT_FOUND = 'SavedObjectsClient/notFound';
|
||||
export function createGenericNotFoundError(type = null, id = null) {
|
||||
|
@ -108,7 +104,6 @@ export function isNotFoundError(error) {
|
|||
return error && error[code] === CODE_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
// 409 - Conflict
|
||||
const CODE_CONFLICT = 'SavedObjectsClient/conflict';
|
||||
export function decorateConflictError(error, reason) {
|
||||
|
@ -118,7 +113,6 @@ export function isConflictError(error) {
|
|||
return error && error[code] === CODE_CONFLICT;
|
||||
}
|
||||
|
||||
|
||||
// 503 - Es Unavailable
|
||||
const CODE_ES_UNAVAILABLE = 'SavedObjectsClient/esUnavailable';
|
||||
export function decorateEsUnavailableError(error, reason) {
|
||||
|
@ -128,7 +122,6 @@ export function isEsUnavailableError(error) {
|
|||
return error && error[code] === CODE_ES_UNAVAILABLE;
|
||||
}
|
||||
|
||||
|
||||
// 503 - Unable to automatically create index because of action.auto_create_index setting
|
||||
const CODE_ES_AUTO_CREATE_INDEX_ERROR = 'SavedObjectsClient/autoCreateIndex';
|
||||
export function createEsAutoCreateIndexError() {
|
||||
|
@ -141,7 +134,6 @@ export function isEsAutoCreateIndexError(error) {
|
|||
return error && error[code] === CODE_ES_AUTO_CREATE_INDEX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// 500 - General Error
|
||||
const CODE_GENERAL_ERROR = 'SavedObjectsClient/generalError';
|
||||
export function decorateGeneralError(error, reason) {
|
||||
|
|
|
@ -45,18 +45,21 @@ describe('savedObjectsClient/errorTypes', () => {
|
|||
const errorObj = createUnsupportedTypeError('someType');
|
||||
|
||||
it('should have the unsupported type message', () => {
|
||||
expect(errorObj).toHaveProperty('message', 'Unsupported saved object type: \'someType\': Bad Request');
|
||||
expect(errorObj).toHaveProperty(
|
||||
'message',
|
||||
"Unsupported saved object type: 'someType': Bad Request"
|
||||
);
|
||||
});
|
||||
|
||||
it('has boom properties', () => {
|
||||
expect(errorObj.output.payload).toMatchObject({
|
||||
statusCode: 400,
|
||||
message: 'Unsupported saved object type: \'someType\': Bad Request',
|
||||
message: "Unsupported saved object type: 'someType': Bad Request",
|
||||
error: 'Bad Request',
|
||||
});
|
||||
});
|
||||
|
||||
it('should be identified by \'isBadRequestError\' method', () => {
|
||||
it("should be identified by 'isBadRequestError' method", () => {
|
||||
expect(isBadRequestError(errorObj)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@ -67,7 +70,7 @@ describe('savedObjectsClient/errorTypes', () => {
|
|||
expect(errorObj.message).toEqual('test reason message: Bad Request');
|
||||
});
|
||||
|
||||
it('should be identified by \'isBadRequestError\' method', () => {
|
||||
it("should be identified by 'isBadRequestError' method", () => {
|
||||
expect(isBadRequestError(errorObj)).toBeTruthy();
|
||||
});
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@ export function includedFields(type, fields) {
|
|||
const sourceFields = typeof fields === 'string' ? [fields] : fields;
|
||||
const sourceType = type || '*';
|
||||
|
||||
return sourceFields.map(f => `${sourceType}.${f}`)
|
||||
return sourceFields
|
||||
.map(f => `${sourceType}.${f}`)
|
||||
.concat('namespace')
|
||||
.concat('type')
|
||||
.concat(fields); // v5 compatibility
|
||||
|
|
|
@ -38,7 +38,7 @@ export class SavedObjectsRepository {
|
|||
serializer,
|
||||
migrator,
|
||||
allowedTypes = [],
|
||||
onBeforeWrite = () => { },
|
||||
onBeforeWrite = () => {},
|
||||
} = options;
|
||||
|
||||
// It's important that we migrate documents / mark them as up-to-date
|
||||
|
@ -52,7 +52,7 @@ export class SavedObjectsRepository {
|
|||
this._index = index;
|
||||
this._mappings = mappings;
|
||||
this._schema = schema;
|
||||
if(allowedTypes.length === 0) {
|
||||
if (allowedTypes.length === 0) {
|
||||
throw new Error('Empty or missing types for saved object repository!');
|
||||
}
|
||||
this._allowedTypes = allowedTypes;
|
||||
|
@ -78,17 +78,11 @@ export class SavedObjectsRepository {
|
|||
* @property {string} [options.namespace]
|
||||
* @property {array} [options.references] - [{ name, type, id }]
|
||||
* @returns {promise} - { id, type, version, attributes }
|
||||
*/
|
||||
*/
|
||||
async create(type, attributes = {}, options = {}) {
|
||||
const {
|
||||
id,
|
||||
migrationVersion,
|
||||
overwrite = false,
|
||||
namespace,
|
||||
references = [],
|
||||
} = options;
|
||||
const { id, migrationVersion, overwrite = false, namespace, references = [] } = options;
|
||||
|
||||
if(!this._isTypeAllowed(type)) {
|
||||
if (!this._isTypeAllowed(type)) {
|
||||
throw errors.createUnsupportedTypeError(type);
|
||||
}
|
||||
|
||||
|
@ -139,22 +133,19 @@ export class SavedObjectsRepository {
|
|||
* @returns {promise} - {saved_objects: [[{ id, type, version, references, attributes, error: { message } }]}
|
||||
*/
|
||||
async bulkCreate(objects, options = {}) {
|
||||
const {
|
||||
namespace,
|
||||
overwrite = false,
|
||||
} = options;
|
||||
const { namespace, overwrite = false } = options;
|
||||
const time = this._getCurrentTime();
|
||||
const bulkCreateParams = [];
|
||||
|
||||
let requestIndexCounter = 0;
|
||||
const expectedResults = objects.map((object) => {
|
||||
if(!this._isTypeAllowed(object.type)) {
|
||||
const expectedResults = objects.map(object => {
|
||||
if (!this._isTypeAllowed(object.type)) {
|
||||
return {
|
||||
response: {
|
||||
id: object.id,
|
||||
type: object.type,
|
||||
error: errors.createUnsupportedTypeError(object.type).output.payload,
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -181,7 +172,7 @@ export class SavedObjectsRepository {
|
|||
_id: expectedResult.rawMigratedDoc._id,
|
||||
},
|
||||
},
|
||||
expectedResult.rawMigratedDoc._source,
|
||||
expectedResult.rawMigratedDoc._source
|
||||
);
|
||||
|
||||
return expectedResult;
|
||||
|
@ -195,7 +186,7 @@ export class SavedObjectsRepository {
|
|||
|
||||
return {
|
||||
saved_objects: expectedResults.map(expectedResult => {
|
||||
if(expectedResult.response) {
|
||||
if (expectedResult.response) {
|
||||
return expectedResult.response;
|
||||
}
|
||||
|
||||
|
@ -209,11 +200,7 @@ export class SavedObjectsRepository {
|
|||
} = Object.values(response)[0];
|
||||
|
||||
const {
|
||||
_source: {
|
||||
type,
|
||||
[type]: attributes,
|
||||
references = [],
|
||||
},
|
||||
_source: { type, [type]: attributes, references = [] },
|
||||
} = rawMigratedDoc;
|
||||
|
||||
const id = requestedId || responseId;
|
||||
|
@ -222,15 +209,15 @@ export class SavedObjectsRepository {
|
|||
return {
|
||||
id,
|
||||
type,
|
||||
error: { statusCode: 409, message: 'version conflict, document already exists' }
|
||||
error: { statusCode: 409, message: 'version conflict, document already exists' },
|
||||
};
|
||||
}
|
||||
return {
|
||||
id,
|
||||
type,
|
||||
error: {
|
||||
message: error.reason || JSON.stringify(error)
|
||||
}
|
||||
message: error.reason || JSON.stringify(error),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -256,13 +243,11 @@ export class SavedObjectsRepository {
|
|||
* @returns {promise}
|
||||
*/
|
||||
async delete(type, id, options = {}) {
|
||||
if(!this._isTypeAllowed(type)) {
|
||||
if (!this._isTypeAllowed(type)) {
|
||||
throw errors.createGenericNotFoundError();
|
||||
}
|
||||
|
||||
const {
|
||||
namespace
|
||||
} = options;
|
||||
const { namespace } = options;
|
||||
|
||||
const response = await this._writeToCluster('delete', {
|
||||
id: this._serializer.generateRawId(namespace, type, id),
|
||||
|
@ -284,7 +269,7 @@ export class SavedObjectsRepository {
|
|||
}
|
||||
|
||||
throw new Error(
|
||||
`Unexpected Elasticsearch DELETE response: ${JSON.stringify({ type, id, response, })}`
|
||||
`Unexpected Elasticsearch DELETE response: ${JSON.stringify({ type, id, response })}`
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -312,8 +297,8 @@ export class SavedObjectsRepository {
|
|||
...getSearchDsl(this._mappings, this._schema, {
|
||||
namespace,
|
||||
type: typesToDelete,
|
||||
})
|
||||
}
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
return await this._writeToCluster('deleteByQuery', esOptions);
|
||||
|
@ -354,23 +339,23 @@ export class SavedObjectsRepository {
|
|||
throw new TypeError(`options.type must be a string or an array of strings`);
|
||||
}
|
||||
|
||||
if(Array.isArray(type)) {
|
||||
if (Array.isArray(type)) {
|
||||
type = type.filter(type => this._isTypeAllowed(type));
|
||||
if(type.length === 0) {
|
||||
if (type.length === 0) {
|
||||
return {
|
||||
page,
|
||||
per_page: perPage,
|
||||
total: 0,
|
||||
saved_objects: []
|
||||
saved_objects: [],
|
||||
};
|
||||
}
|
||||
}else{
|
||||
if(!this._isTypeAllowed(type)) {
|
||||
} else {
|
||||
if (!this._isTypeAllowed(type)) {
|
||||
return {
|
||||
page,
|
||||
per_page: perPage,
|
||||
total: 0,
|
||||
saved_objects: []
|
||||
saved_objects: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -401,8 +386,8 @@ export class SavedObjectsRepository {
|
|||
sortOrder,
|
||||
namespace,
|
||||
hasReference,
|
||||
})
|
||||
}
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
const response = await this._callCluster('search', esOptions);
|
||||
|
@ -414,7 +399,7 @@ export class SavedObjectsRepository {
|
|||
page,
|
||||
per_page: perPage,
|
||||
total: 0,
|
||||
saved_objects: []
|
||||
saved_objects: [],
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -441,9 +426,7 @@ export class SavedObjectsRepository {
|
|||
* ])
|
||||
*/
|
||||
async bulkGet(objects = [], options = {}) {
|
||||
const {
|
||||
namespace
|
||||
} = options;
|
||||
const { namespace } = options;
|
||||
|
||||
if (objects.length === 0) {
|
||||
return { saved_objects: [] };
|
||||
|
@ -454,41 +437,47 @@ export class SavedObjectsRepository {
|
|||
index: this._index,
|
||||
body: {
|
||||
docs: objects.reduce((acc, { type, id }) => {
|
||||
if(this._isTypeAllowed(type)) {
|
||||
if (this._isTypeAllowed(type)) {
|
||||
acc.push({
|
||||
_id: this._serializer.generateRawId(namespace, type, id),
|
||||
});
|
||||
}else{
|
||||
unsupportedTypes.push({ id, type, error: errors.createUnsupportedTypeError(type).output.payload });
|
||||
} else {
|
||||
unsupportedTypes.push({
|
||||
id,
|
||||
type,
|
||||
error: errors.createUnsupportedTypeError(type).output.payload,
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
}, [])
|
||||
}
|
||||
}, []),
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
saved_objects: response.docs.map((doc, i) => {
|
||||
const { id, type } = objects[i];
|
||||
saved_objects: response.docs
|
||||
.map((doc, i) => {
|
||||
const { id, type } = objects[i];
|
||||
|
||||
if (!doc.found) {
|
||||
if (!doc.found) {
|
||||
return {
|
||||
id,
|
||||
type,
|
||||
error: { statusCode: 404, message: 'Not found' },
|
||||
};
|
||||
}
|
||||
|
||||
const time = doc._source.updated_at;
|
||||
return {
|
||||
id,
|
||||
type,
|
||||
error: { statusCode: 404, message: 'Not found' }
|
||||
...(time && { updated_at: time }),
|
||||
version: encodeHitVersion(doc),
|
||||
attributes: doc._source[type],
|
||||
references: doc._source.references || [],
|
||||
migrationVersion: doc._source.migrationVersion,
|
||||
};
|
||||
}
|
||||
|
||||
const time = doc._source.updated_at;
|
||||
return {
|
||||
id,
|
||||
type,
|
||||
...time && { updated_at: time },
|
||||
version: encodeHitVersion(doc),
|
||||
attributes: doc._source[type],
|
||||
references: doc._source.references || [],
|
||||
migrationVersion: doc._source.migrationVersion,
|
||||
};
|
||||
}).concat(unsupportedTypes)
|
||||
})
|
||||
.concat(unsupportedTypes),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -502,18 +491,16 @@ export class SavedObjectsRepository {
|
|||
* @returns {promise} - { id, type, version, attributes }
|
||||
*/
|
||||
async get(type, id, options = {}) {
|
||||
if(!this._isTypeAllowed(type)) {
|
||||
if (!this._isTypeAllowed(type)) {
|
||||
throw errors.createGenericNotFoundError(type, id);
|
||||
}
|
||||
|
||||
const {
|
||||
namespace
|
||||
} = options;
|
||||
const { namespace } = options;
|
||||
|
||||
const response = await this._callCluster('get', {
|
||||
id: this._serializer.generateRawId(namespace, type, id),
|
||||
index: this._index,
|
||||
ignore: [404]
|
||||
ignore: [404],
|
||||
});
|
||||
|
||||
const docNotFound = response.found === false;
|
||||
|
@ -528,7 +515,7 @@ export class SavedObjectsRepository {
|
|||
return {
|
||||
id,
|
||||
type,
|
||||
...updatedAt && { updated_at: updatedAt },
|
||||
...(updatedAt && { updated_at: updatedAt }),
|
||||
version: encodeHitVersion(response),
|
||||
attributes: response._source[type],
|
||||
references: response._source.references || [],
|
||||
|
@ -548,15 +535,11 @@ export class SavedObjectsRepository {
|
|||
* @returns {promise}
|
||||
*/
|
||||
async update(type, id, attributes, options = {}) {
|
||||
if(!this._isTypeAllowed(type)) {
|
||||
if (!this._isTypeAllowed(type)) {
|
||||
throw errors.createGenericNotFoundError(type, id);
|
||||
}
|
||||
|
||||
const {
|
||||
version,
|
||||
namespace,
|
||||
references = [],
|
||||
} = options;
|
||||
const { version, namespace, references = [] } = options;
|
||||
|
||||
const time = this._getCurrentTime();
|
||||
const response = await this._writeToCluster('update', {
|
||||
|
@ -570,7 +553,7 @@ export class SavedObjectsRepository {
|
|||
[type]: attributes,
|
||||
updated_at: time,
|
||||
references,
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -585,7 +568,7 @@ export class SavedObjectsRepository {
|
|||
updated_at: time,
|
||||
version: encodeHitVersion(response),
|
||||
references,
|
||||
attributes
|
||||
attributes,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -606,18 +589,14 @@ export class SavedObjectsRepository {
|
|||
if (typeof counterFieldName !== 'string') {
|
||||
throw new Error('"counterFieldName" argument must be a string');
|
||||
}
|
||||
if(!this._isTypeAllowed(type)) {
|
||||
if (!this._isTypeAllowed(type)) {
|
||||
throw errors.createUnsupportedTypeError(type);
|
||||
}
|
||||
|
||||
const {
|
||||
migrationVersion,
|
||||
namespace,
|
||||
} = options;
|
||||
const { migrationVersion, namespace } = options;
|
||||
|
||||
const time = this._getCurrentTime();
|
||||
|
||||
|
||||
const migrated = this._migrator.migrateDocument({
|
||||
id,
|
||||
type,
|
||||
|
@ -664,8 +643,6 @@ export class SavedObjectsRepository {
|
|||
version: encodeHitVersion(response),
|
||||
attributes: response.get._source[type],
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
async _writeToCluster(method, params) {
|
||||
|
@ -700,8 +677,8 @@ export class SavedObjectsRepository {
|
|||
|
||||
_isTypeAllowed(types) {
|
||||
const toCheck = [].concat(types);
|
||||
for(const type of toCheck) {
|
||||
if(!this._allowedTypes.includes(type)) {
|
||||
for (const type of toCheck) {
|
||||
if (!this._allowedTypes.includes(type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -22,12 +22,9 @@ import { PriorityCollection } from './priority_collection';
|
|||
* Provider for the Scoped Saved Object Client.
|
||||
*/
|
||||
export class ScopedSavedObjectsClientProvider {
|
||||
|
||||
_wrapperFactories = new PriorityCollection();
|
||||
|
||||
constructor({
|
||||
defaultClientFactory
|
||||
}) {
|
||||
constructor({ defaultClientFactory }) {
|
||||
this._originalClientFactory = this._clientFactory = defaultClientFactory;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ test(`uses default client factory when one isn't set`, () => {
|
|||
const request = Symbol();
|
||||
|
||||
const clientProvider = new ScopedSavedObjectsClientProvider({
|
||||
defaultClientFactory: defaultClientFactoryMock
|
||||
defaultClientFactory: defaultClientFactoryMock,
|
||||
});
|
||||
const result = clientProvider.getClient(request);
|
||||
|
||||
|
@ -43,7 +43,7 @@ test(`uses custom client factory when one is set`, () => {
|
|||
const customClientFactoryMock = jest.fn().mockReturnValue(returnValue);
|
||||
|
||||
const clientProvider = new ScopedSavedObjectsClientProvider({
|
||||
defaultClientFactory: defaultClientFactoryMock
|
||||
defaultClientFactory: defaultClientFactoryMock,
|
||||
});
|
||||
clientProvider.setClientFactory(customClientFactoryMock);
|
||||
const result = clientProvider.getClient(request);
|
||||
|
@ -58,9 +58,9 @@ test(`uses custom client factory when one is set`, () => {
|
|||
|
||||
test(`throws error when more than one scoped saved objects client factory is set`, () => {
|
||||
const clientProvider = new ScopedSavedObjectsClientProvider({});
|
||||
clientProvider.setClientFactory(() => { });
|
||||
clientProvider.setClientFactory(() => {});
|
||||
expect(() => {
|
||||
clientProvider.setClientFactory(() => { });
|
||||
clientProvider.setClientFactory(() => {});
|
||||
}).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
|
||||
|
@ -68,7 +68,7 @@ test(`invokes and uses wrappers in specified order`, () => {
|
|||
const defaultClient = Symbol();
|
||||
const defaultClientFactoryMock = jest.fn().mockReturnValue(defaultClient);
|
||||
const clientProvider = new ScopedSavedObjectsClientProvider({
|
||||
defaultClientFactory: defaultClientFactoryMock
|
||||
defaultClientFactory: defaultClientFactoryMock,
|
||||
});
|
||||
const firstWrappedClient = Symbol('first client');
|
||||
const firstClientWrapperFactoryMock = jest.fn().mockReturnValue(firstWrappedClient);
|
||||
|
@ -83,10 +83,10 @@ test(`invokes and uses wrappers in specified order`, () => {
|
|||
expect(actualClient).toBe(firstWrappedClient);
|
||||
expect(firstClientWrapperFactoryMock).toHaveBeenCalledWith({
|
||||
request,
|
||||
client: secondWrapperClient
|
||||
client: secondWrapperClient,
|
||||
});
|
||||
expect(secondClientWrapperFactoryMock).toHaveBeenCalledWith({
|
||||
request,
|
||||
client: defaultClient
|
||||
client: defaultClient,
|
||||
});
|
||||
});
|
||||
|
|
|
@ -44,7 +44,6 @@ function getTypes(mappings, type) {
|
|||
* @return {Object}
|
||||
*/
|
||||
function getFieldsForTypes(searchFields, types) {
|
||||
|
||||
if (!searchFields || !searchFields.length) {
|
||||
return {
|
||||
lenient: true,
|
||||
|
@ -53,10 +52,10 @@ function getFieldsForTypes(searchFields, types) {
|
|||
}
|
||||
|
||||
return {
|
||||
fields: searchFields.reduce((acc, field) => [
|
||||
...acc,
|
||||
...types.map(prefix => `${prefix}.${field}`)
|
||||
], []),
|
||||
fields: searchFields.reduce(
|
||||
(acc, field) => [...acc, ...types.map(prefix => `${prefix}.${field}`)],
|
||||
[]
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -76,19 +75,16 @@ function getClauseForType(schema, namespace, type) {
|
|||
if (namespace && !schema.isNamespaceAgnostic(type)) {
|
||||
return {
|
||||
bool: {
|
||||
must: [
|
||||
{ term: { type } },
|
||||
{ term: { namespace } },
|
||||
]
|
||||
}
|
||||
must: [{ term: { type } }, { term: { namespace } }],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
bool: {
|
||||
must: [{ term: { type } }],
|
||||
must_not: [{ exists: { field: 'namespace' } }]
|
||||
}
|
||||
must_not: [{ exists: { field: 'namespace' } }],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -103,38 +99,51 @@ function getClauseForType(schema, namespace, type) {
|
|||
* @param {Object} hasReference
|
||||
* @return {Object}
|
||||
*/
|
||||
export function getQueryParams(mappings, schema, namespace, type, search, searchFields, defaultSearchOperator, hasReference) {
|
||||
export function getQueryParams(
|
||||
mappings,
|
||||
schema,
|
||||
namespace,
|
||||
type,
|
||||
search,
|
||||
searchFields,
|
||||
defaultSearchOperator,
|
||||
hasReference
|
||||
) {
|
||||
const types = getTypes(mappings, type);
|
||||
const bool = {
|
||||
filter: [{
|
||||
bool: {
|
||||
must: hasReference
|
||||
? [{
|
||||
nested: {
|
||||
path: 'references',
|
||||
query: {
|
||||
bool: {
|
||||
must: [
|
||||
{
|
||||
term: {
|
||||
'references.id': hasReference.id,
|
||||
filter: [
|
||||
{
|
||||
bool: {
|
||||
must: hasReference
|
||||
? [
|
||||
{
|
||||
nested: {
|
||||
path: 'references',
|
||||
query: {
|
||||
bool: {
|
||||
must: [
|
||||
{
|
||||
term: {
|
||||
'references.id': hasReference.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'references.type': hasReference.type,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
'references.type': hasReference.type,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}]
|
||||
: undefined,
|
||||
should: types.map(type => getClauseForType(schema, namespace, type)),
|
||||
minimum_should_match: 1
|
||||
}
|
||||
}],
|
||||
]
|
||||
: undefined,
|
||||
should: types.map(type => getClauseForType(schema, namespace, type)),
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
if (search) {
|
||||
|
@ -142,13 +151,10 @@ export function getQueryParams(mappings, schema, namespace, type, search, search
|
|||
{
|
||||
simple_query_string: {
|
||||
query: search,
|
||||
...getFieldsForTypes(
|
||||
searchFields,
|
||||
types
|
||||
),
|
||||
...getFieldsForTypes(searchFields, types),
|
||||
...(defaultSearchOperator ? { default_operator: defaultSearchOperator } : {}),
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -43,7 +43,16 @@ export function getSearchDsl(mappings, schema, options = {}) {
|
|||
}
|
||||
|
||||
return {
|
||||
...getQueryParams(mappings, schema, namespace, type, search, searchFields, defaultSearchOperator, hasReference),
|
||||
...getQueryParams(
|
||||
mappings,
|
||||
schema,
|
||||
namespace,
|
||||
type,
|
||||
search,
|
||||
searchFields,
|
||||
defaultSearchOperator,
|
||||
hasReference
|
||||
),
|
||||
...getSortingParams(mappings, type, sortField, sortOrder),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -33,18 +33,26 @@ describe('getSearchDsl', () => {
|
|||
describe('validation', () => {
|
||||
it('throws when type is not specified', () => {
|
||||
expect(() => {
|
||||
getSearchDsl({}, {}, {
|
||||
type: undefined,
|
||||
sortField: 'title'
|
||||
});
|
||||
getSearchDsl(
|
||||
{},
|
||||
{},
|
||||
{
|
||||
type: undefined,
|
||||
sortField: 'title',
|
||||
}
|
||||
);
|
||||
}).toThrowError(/type must be specified/);
|
||||
});
|
||||
it('throws when sortOrder without sortField', () => {
|
||||
expect(() => {
|
||||
getSearchDsl({}, {}, {
|
||||
type: 'foo',
|
||||
sortOrder: 'desc'
|
||||
});
|
||||
getSearchDsl(
|
||||
{},
|
||||
{},
|
||||
{
|
||||
type: 'foo',
|
||||
sortOrder: 'desc',
|
||||
}
|
||||
);
|
||||
}).toThrowError(/sortOrder requires a sortField/);
|
||||
});
|
||||
});
|
||||
|
@ -75,7 +83,7 @@ describe('getSearchDsl', () => {
|
|||
opts.search,
|
||||
opts.searchFields,
|
||||
opts.defaultSearchOperator,
|
||||
opts.hasReference,
|
||||
opts.hasReference
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -86,7 +94,7 @@ describe('getSearchDsl', () => {
|
|||
const opts = {
|
||||
type: 'foo',
|
||||
sortField: 'bar',
|
||||
sortOrder: 'baz'
|
||||
sortOrder: 'baz',
|
||||
};
|
||||
|
||||
getSearchDsl(mappings, schema, opts);
|
||||
|
@ -95,7 +103,7 @@ describe('getSearchDsl', () => {
|
|||
mappings,
|
||||
opts.type,
|
||||
opts.sortField,
|
||||
opts.sortOrder,
|
||||
opts.sortOrder
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -31,27 +31,33 @@ export function getSortingParams(mappings, type, sortField, sortOrder) {
|
|||
|
||||
if (TOP_LEVEL_FIELDS.includes(sortField)) {
|
||||
return {
|
||||
sort: [{
|
||||
[sortField]: {
|
||||
order: sortOrder,
|
||||
sort: [
|
||||
{
|
||||
[sortField]: {
|
||||
order: sortOrder,
|
||||
},
|
||||
},
|
||||
}],
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
if (types.length > 1) {
|
||||
const rootField = getProperty(mappings, sortField);
|
||||
if (!rootField) {
|
||||
throw Boom.badRequest(`Unable to sort multiple types by field ${sortField}, not a root property`);
|
||||
throw Boom.badRequest(
|
||||
`Unable to sort multiple types by field ${sortField}, not a root property`
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
sort: [{
|
||||
[sortField]: {
|
||||
order: sortOrder,
|
||||
unmapped_type: rootField.type
|
||||
}
|
||||
}]
|
||||
sort: [
|
||||
{
|
||||
[sortField]: {
|
||||
order: sortOrder,
|
||||
unmapped_type: rootField.type,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -63,11 +69,13 @@ export function getSortingParams(mappings, type, sortField, sortOrder) {
|
|||
}
|
||||
|
||||
return {
|
||||
sort: [{
|
||||
[key]: {
|
||||
order: sortOrder,
|
||||
unmapped_type: field.type
|
||||
}
|
||||
}]
|
||||
sort: [
|
||||
{
|
||||
[key]: {
|
||||
order: sortOrder,
|
||||
unmapped_type: field.type,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -25,9 +25,9 @@ const MAPPINGS = {
|
|||
type: 'text',
|
||||
fields: {
|
||||
raw: {
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
pending: {
|
||||
properties: {
|
||||
|
@ -35,11 +35,11 @@ const MAPPINGS = {
|
|||
type: 'text',
|
||||
fields: {
|
||||
raw: {
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
saved: {
|
||||
properties: {
|
||||
|
@ -47,128 +47,124 @@ const MAPPINGS = {
|
|||
type: 'text',
|
||||
fields: {
|
||||
raw: {
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
obj: {
|
||||
properties: {
|
||||
key1: {
|
||||
type: 'text'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
describe('searchDsl/getSortParams', () => {
|
||||
describe('no sortField, type, or order', () => {
|
||||
it('returns no params', () => {
|
||||
expect(getSortingParams(MAPPINGS))
|
||||
.toEqual({});
|
||||
expect(getSortingParams(MAPPINGS)).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('type, no sortField', () => {
|
||||
it('returns no params', () => {
|
||||
expect(getSortingParams(MAPPINGS, 'pending'))
|
||||
.toEqual({});
|
||||
expect(getSortingParams(MAPPINGS, 'pending')).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('type, order, no sortField', () => {
|
||||
it('returns no params', () => {
|
||||
expect(getSortingParams(MAPPINGS, 'saved', null, 'desc'))
|
||||
.toEqual({});
|
||||
expect(getSortingParams(MAPPINGS, 'saved', null, 'desc')).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('sortField no direction', () => {
|
||||
describe('sortField is simple property with single type', () => {
|
||||
it('returns correct params', () => {
|
||||
expect(getSortingParams(MAPPINGS, 'saved', 'title'))
|
||||
.toEqual({
|
||||
sort: [
|
||||
{
|
||||
'saved.title': {
|
||||
order: undefined,
|
||||
unmapped_type: 'text'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
expect(getSortingParams(MAPPINGS, 'saved', 'title')).toEqual({
|
||||
sort: [
|
||||
{
|
||||
'saved.title': {
|
||||
order: undefined,
|
||||
unmapped_type: 'text',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('sortField is simple root property with multiple types', () => {
|
||||
it('returns correct params', () => {
|
||||
expect(getSortingParams(MAPPINGS, ['saved', 'pending'], 'type'))
|
||||
.toEqual({
|
||||
sort: [
|
||||
{
|
||||
'type': {
|
||||
order: undefined,
|
||||
unmapped_type: 'text'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
expect(getSortingParams(MAPPINGS, ['saved', 'pending'], 'type')).toEqual({
|
||||
sort: [
|
||||
{
|
||||
type: {
|
||||
order: undefined,
|
||||
unmapped_type: 'text',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('sortField is simple non-root property with multiple types', () => {
|
||||
it('returns correct params', () => {
|
||||
expect(() => getSortingParams(MAPPINGS, ['saved', 'pending'], 'title')).toThrowErrorMatchingSnapshot();
|
||||
expect(() =>
|
||||
getSortingParams(MAPPINGS, ['saved', 'pending'], 'title')
|
||||
).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
});
|
||||
describe('sortField is multi-field with single type', () => {
|
||||
it('returns correct params', () => {
|
||||
expect(getSortingParams(MAPPINGS, 'saved', 'title.raw'))
|
||||
.toEqual({
|
||||
sort: [
|
||||
{
|
||||
'saved.title.raw': {
|
||||
order: undefined,
|
||||
unmapped_type: 'keyword'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
expect(getSortingParams(MAPPINGS, 'saved', 'title.raw')).toEqual({
|
||||
sort: [
|
||||
{
|
||||
'saved.title.raw': {
|
||||
order: undefined,
|
||||
unmapped_type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('sortField is multi-field with single type as array', () => {
|
||||
it('returns correct params', () => {
|
||||
expect(getSortingParams(MAPPINGS, ['saved'], 'title.raw'))
|
||||
.toEqual({
|
||||
sort: [
|
||||
{
|
||||
'saved.title.raw': {
|
||||
order: undefined,
|
||||
unmapped_type: 'keyword'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
expect(getSortingParams(MAPPINGS, ['saved'], 'title.raw')).toEqual({
|
||||
sort: [
|
||||
{
|
||||
'saved.title.raw': {
|
||||
order: undefined,
|
||||
unmapped_type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('sortField is root multi-field with multiple types', () => {
|
||||
it('returns correct params', () => {
|
||||
expect(getSortingParams(MAPPINGS, ['saved', 'pending'], 'type.raw'))
|
||||
.toEqual({
|
||||
sort: [
|
||||
{
|
||||
'type.raw': {
|
||||
order: undefined,
|
||||
unmapped_type: 'keyword'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
expect(getSortingParams(MAPPINGS, ['saved', 'pending'], 'type.raw')).toEqual({
|
||||
sort: [
|
||||
{
|
||||
'type.raw': {
|
||||
order: undefined,
|
||||
unmapped_type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('sortField is not-root multi-field with multiple types', () => {
|
||||
it('returns correct params', () => {
|
||||
expect(() => getSortingParams(MAPPINGS, ['saved', 'pending'], 'title.raw')).toThrowErrorMatchingSnapshot();
|
||||
expect(() =>
|
||||
getSortingParams(MAPPINGS, ['saved', 'pending'], 'title.raw')
|
||||
).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -176,72 +172,72 @@ describe('searchDsl/getSortParams', () => {
|
|||
describe('sort with direction', () => {
|
||||
describe('sortField is simple property with single type', () => {
|
||||
it('returns correct params', () => {
|
||||
expect(getSortingParams(MAPPINGS, 'saved', 'title', 'desc'))
|
||||
.toEqual({
|
||||
sort: [
|
||||
{
|
||||
'saved.title': {
|
||||
order: 'desc',
|
||||
unmapped_type: 'text'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
expect(getSortingParams(MAPPINGS, 'saved', 'title', 'desc')).toEqual({
|
||||
sort: [
|
||||
{
|
||||
'saved.title': {
|
||||
order: 'desc',
|
||||
unmapped_type: 'text',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('sortField is root simple property with multiple type', () => {
|
||||
it('returns correct params', () => {
|
||||
expect(getSortingParams(MAPPINGS, ['saved', 'pending'], 'type', 'desc'))
|
||||
.toEqual({
|
||||
sort: [
|
||||
{
|
||||
'type': {
|
||||
order: 'desc',
|
||||
unmapped_type: 'text'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
expect(getSortingParams(MAPPINGS, ['saved', 'pending'], 'type', 'desc')).toEqual({
|
||||
sort: [
|
||||
{
|
||||
type: {
|
||||
order: 'desc',
|
||||
unmapped_type: 'text',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('sortFields is non-root simple property with multiple types', () => {
|
||||
it('returns correct params', () => {
|
||||
expect(() => getSortingParams(MAPPINGS, ['saved', 'pending'], 'title', 'desc')).toThrowErrorMatchingSnapshot();
|
||||
expect(() =>
|
||||
getSortingParams(MAPPINGS, ['saved', 'pending'], 'title', 'desc')
|
||||
).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
});
|
||||
describe('sortField is multi-field with single type', () => {
|
||||
it('returns correct params', () => {
|
||||
expect(getSortingParams(MAPPINGS, 'saved', 'title.raw', 'asc'))
|
||||
.toEqual({
|
||||
sort: [
|
||||
{
|
||||
'saved.title.raw': {
|
||||
order: 'asc',
|
||||
unmapped_type: 'keyword'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
expect(getSortingParams(MAPPINGS, 'saved', 'title.raw', 'asc')).toEqual({
|
||||
sort: [
|
||||
{
|
||||
'saved.title.raw': {
|
||||
order: 'asc',
|
||||
unmapped_type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('sortField is root multi-field with multiple types', () => {
|
||||
it('returns correct params', () => {
|
||||
expect(getSortingParams(MAPPINGS, ['saved', 'pending'], 'type.raw', 'asc'))
|
||||
.toEqual({
|
||||
sort: [
|
||||
{
|
||||
'type.raw': {
|
||||
order: 'asc',
|
||||
unmapped_type: 'keyword'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
expect(getSortingParams(MAPPINGS, ['saved', 'pending'], 'type.raw', 'asc')).toEqual({
|
||||
sort: [
|
||||
{
|
||||
'type.raw': {
|
||||
order: 'asc',
|
||||
unmapped_type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('sortField is non-root multi-field with multiple types', () => {
|
||||
it('returns correct params', () => {
|
||||
expect(() => getSortingParams(MAPPINGS, ['saved', 'pending'], 'title.raw', 'asc')).toThrowErrorMatchingSnapshot();
|
||||
expect(() =>
|
||||
getSortingParams(MAPPINGS, ['saved', 'pending'], 'title.raw', 'asc')
|
||||
).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,9 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
errors,
|
||||
} from './lib';
|
||||
import { errors } from './lib';
|
||||
|
||||
export class SavedObjectsClient {
|
||||
constructor(repository) {
|
||||
|
@ -91,8 +89,8 @@ export class SavedObjectsClient {
|
|||
*
|
||||
* @type {ErrorHelpers} see ./lib/errors
|
||||
*/
|
||||
static errors = errors
|
||||
errors = errors
|
||||
static errors = errors;
|
||||
errors = errors;
|
||||
|
||||
/**
|
||||
* Persists an object
|
||||
|
@ -106,7 +104,7 @@ export class SavedObjectsClient {
|
|||
* @property {string} [options.namespace]
|
||||
* @property {array} [options.references] - [{ name, type, id }]
|
||||
* @returns {promise} - { id, type, version, attributes }
|
||||
*/
|
||||
*/
|
||||
async create(type, attributes = {}, options = {}) {
|
||||
return this._repository.create(type, attributes, options);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue