[Saved objects] Prepare SO management for versionable types (#149495)

## Summary

Part of preparing HTTP APIs and associated interfaces for versioning:

* Add domain-specific interfaces to the saved object management plugin
    * Add a V1 interface of domain types to `common`
    * Remove use of deprecated `SavedObject` type from public
* Follows on from https://github.com/elastic/kibana/pull/148602


Related https://github.com/elastic/kibana/issues/149098

Fixes https://github.com/elastic/kibana/pull/149495

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Jean-Louis Leysens 2023-02-02 17:02:38 +01:00 committed by GitHub
parent b1617498a5
commit df809bd53a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 383 additions and 211 deletions

View file

@ -12,6 +12,6 @@ export type {
SavedObjectRelation,
SavedObjectRelationKind,
SavedObjectInvalidRelation,
SavedObjectGetRelationshipsResponse,
SavedObjectManagementTypeInfo,
v1,
} from './types';

View file

@ -1,61 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { SavedObject } from '@kbn/core/types';
import type { SavedObjectsNamespaceType } from '@kbn/core/public';
/**
* The metadata injected into a {@link SavedObject | saved object} when returning
* {@link SavedObjectWithMetadata | enhanced objects} from the plugin API endpoints.
*/
export interface SavedObjectMetadata {
icon?: string;
title?: string;
editUrl?: string;
inAppUrl?: { path: string; uiCapabilitiesPath: string };
namespaceType?: SavedObjectsNamespaceType;
hiddenType?: boolean;
}
/**
* A {@link SavedObject | saved object} enhanced with meta properties used by the client-side plugin.
*/
export type SavedObjectWithMetadata<T = unknown> = SavedObject<T> & {
meta: SavedObjectMetadata;
};
export type SavedObjectRelationKind = 'child' | 'parent';
/**
* Represents a relation between two {@link SavedObject | saved object}
*/
export interface SavedObjectRelation {
id: string;
type: string;
relationship: SavedObjectRelationKind;
meta: SavedObjectMetadata;
}
export interface SavedObjectInvalidRelation {
id: string;
type: string;
relationship: SavedObjectRelationKind;
error: string;
}
export interface SavedObjectGetRelationshipsResponse {
relations: SavedObjectRelation[];
invalidRelations: SavedObjectInvalidRelation[];
}
export interface SavedObjectManagementTypeInfo {
name: string;
namespaceType: SavedObjectsNamespaceType;
hidden: boolean;
displayName: string;
}

View file

@ -0,0 +1,58 @@
## Versioned interfaces
This folder contains types that are shared between the server and client:
```ts
// v1.ts
export interface SavedObjectWithMetadata { name: string }
// index.ts
import * as v1 from './v1';
export type { v1 };
// Used elsewhere
import type { v1 } from '../common';
const myObject: v1.SavedObjectWithMetadata = { name: 'my object' };
```
**Do not alter a versioned type**. Types may be in use by clients (if the code is released).
Alterations must be made on a new version of the TS interface.
## Create a new version
Versions in this plugin are determined using monotonically increasing numbers: 1, 2, 3, etc.
1. Find the latest version, e.g: `v2`.
2. Create a new file, e.g., `v3.ts` if it does not exist.
3. Copy the type(s) to change from previous version. E.g. `v2.ts`'s `SavedObjectWithMetadata`.
4. Alter the interface as needed
5. Re-export `v2` types to "inherit" the entire previous version's types: `export * from './v2';`
6. Export your new version from latest: `export * from './v3';`. This may result in TS errors
to be fixed.
7. Export your new file from index.ts as `v3`.
Your `v3.ts` file should look something like:
```ts
export * from './v3';
export interface SavedObjectWithMetadata { name: string; a_new_field: string; }
```
In this way the entire API is accessible from `v3` including types that may
not have changed.
Any alterations post-release must be in a new version (start at step 1).
## The `latest.ts` file
The `latest.ts` file is a container for all "latest" versions of types. This is useful
for app code that always needs the latest version of your interfaces. E.g.:
```ts
import type { SavedObjectWithMetadata } from '../common';
```
Notice that there is no version number mentioned. Either in the interface name
or import path. To update the "latest" type you must re-export the new version
from the appropriate versioned path.

View file

@ -0,0 +1,19 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export type {
SavedObjectInvalidRelation,
SavedObjectManagementTypeInfo,
SavedObjectMetadata,
SavedObjectRelation,
SavedObjectRelationKind,
SavedObjectWithMetadata,
} from './latest';
import type * as v1 from './v1';
export type { v1 };

View file

@ -6,8 +6,4 @@
* Side Public License, v 1.
*/
import { mapKeys, camelCase } from 'lodash';
export function keysToCamelCaseShallow(object: Record<string, any>) {
return mapKeys(object, (value, key) => camelCase(key));
}
export * from './v1';

View file

@ -0,0 +1,178 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { SavedObjectError } from '@kbn/core/types';
import type { SavedObjectsNamespaceType } from '@kbn/core/public';
/** Domain interfaces */
/**
* Saved Object Management metadata associated with a saved object. See
* {@link SavedObjectWithMetadata}.
*/
export interface SavedObjectMetadata {
icon?: string;
title?: string;
editUrl?: string;
inAppUrl?: { path: string; uiCapabilitiesPath: string };
namespaceType?: SavedObjectsNamespaceType;
hiddenType?: boolean;
}
/**
* One saved object's reference to another saved object.
*/
export interface SavedObjectReference {
name: string;
type: string;
id: string;
}
/**
* A saved object.
*
* @note This is intended as a domain-specific representation of a SavedObject
* which is intended for server-side only use.
*/
export interface SavedObjectWithMetadata<T = unknown> {
id: string;
type: string;
meta: SavedObjectMetadata;
error?: SavedObjectError;
created_at?: string;
updated_at?: string;
attributes: T;
namespaces?: string[];
references: SavedObjectReference[];
}
export type SavedObjectRelationKind = 'child' | 'parent';
/**
* Represents a relation between two {@link SavedObjectWithMetadata | saved objects}.
*/
export interface SavedObjectRelation {
id: string;
type: string;
relationship: SavedObjectRelationKind;
meta: SavedObjectMetadata;
}
/**
* Represents a relation between two {@link SavedObjectWithMetadata | saved objects}.
*/
export interface SavedObjectInvalidRelation {
id: string;
type: string;
relationship: SavedObjectRelationKind;
error: string;
}
export interface SavedObjectManagementTypeInfo {
name: string;
// TODO: Fix. We should not directly expose these values to public code.
namespaceType: SavedObjectsNamespaceType;
hidden: boolean;
displayName: string;
}
/** HTTP API interfaces */
export type BulkGetBodyHTTP = Array<{
id: string;
type: string;
}>;
export type BulkGetResponseHTTP = SavedObjectWithMetadata[];
export type BulkDeleteBodyHTTP = Array<{
type: string;
id: string;
}>;
export type BulkDeleteResponseHTTP = Array<{
/** The ID of the saved object */
id: string;
/** The type of the saved object */
type: string;
/** The status of deleting the object: true for deleted, false for error */
success: boolean;
/** Reason the object could not be deleted (success is false) */
error?: SavedObjectError;
}>;
export type FindSearchOperatorHTTP = 'AND' | 'OR';
export type FindSortOrderHTTP = 'asc' | 'desc';
export interface ReferenceHTTP {
type: string;
id: string;
}
export interface FindQueryHTTP {
perPage?: number;
page?: number;
type: string | string[];
// TODO: Fix. this API allows writing an arbitrary query that is passed straight to our persistence layer, thus leaking SO attributes to the public...
search?: string;
defaultSearchOperator?: FindSearchOperatorHTTP;
// TODO: Fix. this API allows sorting by any field, thus leaking SO attributes to the public...
sortField?: string;
sortOrder?: FindSortOrderHTTP;
hasReference?: ReferenceHTTP | ReferenceHTTP[];
hasReferenceOperator?: FindSearchOperatorHTTP;
// TODO: Fix. This exposes attribute schemas to clients.
fields?: string | string[];
}
export interface FindResponseHTTP {
saved_objects: SavedObjectWithMetadata[];
total: number;
page: number;
per_page: number;
}
export interface GetAllowedTypesResponseHTTP {
types: SavedObjectManagementTypeInfo[];
}
export interface RelationshipsParamsHTTP {
type: string;
id: string;
}
export interface RelationshipsQueryHTTP {
size: number;
savedObjectTypes: string | string[];
}
export interface RelationshipsResponseHTTP {
relations: SavedObjectRelation[];
invalidRelations: SavedObjectInvalidRelation[];
}
export interface ScrollCountBodyHTTP {
typesToInclude: string[];
// TODO: Fix. this API allows writing an arbitrary query that is passed straight to our persistence layer, thus leaking SO attributes to the public...
searchString?: string;
references?: Array<{ type: string; id: string }>;
}
export interface DeleteObjectBodyHTTP {
id: string;
type: string;
}
export interface DeleteObjectResponseHTTP {
id: string;
}
/**
* In this case "string" is a direct mapping from "typesToInlcude" in {@link ScrollCountBodyHTTP['typesToInclude']']}
*/
export type ScrollCountResponseHTTP = Record<string, number>;

View file

@ -6,24 +6,14 @@
* Side Public License, v 1.
*/
import { HttpStart } from '@kbn/core/public';
import { SavedObjectError, SavedObjectTypeIdTuple } from '@kbn/core-saved-objects-common';
interface SavedObjectDeleteStatus {
id: string;
success: boolean;
type: string;
error?: SavedObjectError;
}
import type { HttpStart } from '@kbn/core/public';
import type { v1 } from '../../common';
export function bulkDeleteObjects(
http: HttpStart,
objects: SavedObjectTypeIdTuple[]
): Promise<SavedObjectDeleteStatus[]> {
return http.post<SavedObjectDeleteStatus[]>(
'/internal/kibana/management/saved_objects/_bulk_delete',
{
body: JSON.stringify(objects),
}
);
objects: v1.BulkDeleteBodyHTTP
): Promise<v1.BulkDeleteResponseHTTP> {
return http.post('/internal/kibana/management/saved_objects/_bulk_delete', {
body: JSON.stringify(objects),
});
}

View file

@ -6,15 +6,14 @@
* Side Public License, v 1.
*/
import { HttpStart } from '@kbn/core/public';
import { SavedObjectWithMetadata } from '../types';
import type { HttpStart } from '@kbn/core/public';
import type { v1 } from '../../common';
export async function bulkGetObjects(
http: HttpStart,
objects: Array<{ type: string; id: string }>
): Promise<SavedObjectWithMetadata[]> {
return await http.post<SavedObjectWithMetadata[]>(
`/api/kibana/management/saved_objects/_bulk_get`,
{ body: JSON.stringify(objects) }
);
objects: v1.BulkGetBodyHTTP
): Promise<v1.BulkGetResponseHTTP> {
return await http.post(`/api/kibana/management/saved_objects/_bulk_get`, {
body: JSON.stringify(objects),
});
}

View file

@ -1,25 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { keysToCamelCaseShallow } from './case_conversion';
describe('keysToCamelCaseShallow', () => {
test("should convert all of an object's keys to camel case", () => {
const data = {
camelCase: 'camelCase',
'kebab-case': 'kebabCase',
snake_case: 'snakeCase',
};
const result = keysToCamelCaseShallow(data);
expect(result.camelCase).toBe('camelCase');
expect(result.kebabCase).toBe('kebabCase');
expect(result.snakeCase).toBe('snakeCase');
});
});

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { HttpStart, SavedObjectsFindOptionsReference } from '@kbn/core/public';
import type { HttpStart, SavedObjectsFindOptionsReference } from '@kbn/core/public';
export async function fetchExportByTypeAndSearch({
http,

View file

@ -6,32 +6,17 @@
* Side Public License, v 1.
*/
import { HttpStart, SavedObjectsFindOptions } from '@kbn/core/public';
import { keysToCamelCaseShallow } from './case_conversion';
import { SavedObjectWithMetadata } from '../types';
interface SavedObjectsFindResponse {
total: number;
page: number;
perPage: number;
savedObjects: SavedObjectWithMetadata[];
}
import { HttpStart } from '@kbn/core/public';
import type { v1 } from '../../common';
export async function findObjects(
http: HttpStart,
findOptions: SavedObjectsFindOptions
): Promise<SavedObjectsFindResponse> {
const response = await http.get<Record<string, any>>(
'/api/kibana/management/saved_objects/_find',
{
query: {
...findOptions,
hasReference: findOptions.hasReference
? JSON.stringify(findOptions.hasReference)
: undefined,
} as Record<string, any>,
}
);
return keysToCamelCaseShallow(response) as SavedObjectsFindResponse;
findOptions: v1.FindQueryHTTP
): Promise<v1.FindResponseHTTP> {
return http.get('/api/kibana/management/saved_objects/_find', {
query: {
...findOptions,
hasReference: findOptions.hasReference ? JSON.stringify(findOptions.hasReference) : undefined,
} as Record<string, any>,
});
}

View file

@ -7,14 +7,12 @@
*/
import type { HttpStart } from '@kbn/core/public';
import type { SavedObjectManagementTypeInfo } from '../../common/types';
import type { v1 } from '../../common';
interface GetAllowedTypesResponse {
types: SavedObjectManagementTypeInfo[];
}
export async function getAllowedTypes(http: HttpStart): Promise<SavedObjectManagementTypeInfo[]> {
const response = await http.get<GetAllowedTypesResponse>(
export async function getAllowedTypes(
http: HttpStart
): Promise<v1.GetAllowedTypesResponseHTTP['types']> {
const response = await http.get<v1.GetAllowedTypesResponseHTTP>(
'/api/kibana/management/saved_objects/_allowed_types'
);
return response.types;

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { SavedObjectGetRelationshipsResponse } from '../types';
import { v1 } from '../../common';
import { httpServiceMock } from '@kbn/core/public/mocks';
import { getRelationships } from './get_relationships';
@ -23,7 +23,7 @@ describe('getRelationships', () => {
});
it('should handle successful responses', async () => {
const serverResponse: SavedObjectGetRelationshipsResponse = {
const serverResponse: v1.RelationshipsResponseHTTP = {
relations: [],
invalidRelations: [],
};

View file

@ -6,21 +6,21 @@
* Side Public License, v 1.
*/
import { HttpStart } from '@kbn/core/public';
import type { HttpStart } from '@kbn/core/public';
import { get } from 'lodash';
import { SavedObjectGetRelationshipsResponse } from '../types';
import type { v1 } from '../../common';
export async function getRelationships(
http: HttpStart,
type: string,
id: string,
savedObjectTypes: string[]
): Promise<SavedObjectGetRelationshipsResponse> {
): Promise<v1.RelationshipsResponseHTTP> {
const url = `/api/kibana/management/saved_objects/relationships/${encodeURIComponent(
type
)}/${encodeURIComponent(id)}`;
try {
return await http.get<SavedObjectGetRelationshipsResponse>(url, {
return await http.get(url, {
query: {
savedObjectTypes,
},

View file

@ -6,7 +6,8 @@
* Side Public License, v 1.
*/
import { HttpStart, SavedObjectsFindOptionsReference } from '@kbn/core/public';
import type { HttpStart, SavedObjectsFindOptionsReference } from '@kbn/core/public';
import type { v1 } from '../../common';
export async function getSavedObjectCounts({
http,
@ -18,9 +19,8 @@ export async function getSavedObjectCounts({
typesToInclude: string[];
searchString?: string;
references?: SavedObjectsFindOptionsReference[];
}): Promise<Record<string, number>> {
return await http.post<Record<string, number>>(
`/api/kibana/management/saved_objects/scroll/counts`,
{ body: JSON.stringify({ typesToInclude, searchString, references }) }
);
}): Promise<v1.ScrollCountResponseHTTP> {
return await http.post(`/api/kibana/management/saved_objects/scroll/counts`, {
body: JSON.stringify({ typesToInclude, searchString, references }),
});
}

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import {
import type {
SavedObjectsImportConflictError,
SavedObjectsImportAmbiguousConflictError,
SavedObjectsImportUnknownError,

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import {
import type {
SavedObjectsImportResponse,
SavedObjectsImportConflictError,
SavedObjectsImportAmbiguousConflictError,

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import {
import type {
HttpStart,
SavedObjectsImportConflictError,
SavedObjectsImportRetry,

View file

@ -28,17 +28,17 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { IBasePath } from '@kbn/core/public';
import type { SavedObjectManagementTypeInfo } from '../../../../common/types';
import { getDefaultTitle, getSavedObjectLabel } from '../../../lib';
import type { v1 } from '../../../../common';
import {
SavedObjectWithMetadata,
SavedObjectRelationKind,
SavedObjectRelation,
SavedObjectInvalidRelation,
SavedObjectGetRelationshipsResponse,
} from '../../../types';
export interface RelationshipsProps {
basePath: IBasePath;
getRelationships: (type: string, id: string) => Promise<SavedObjectGetRelationshipsResponse>;
getRelationships: (type: string, id: string) => Promise<v1.RelationshipsResponseHTTP>;
savedObject: SavedObjectWithMetadata;
close: () => void;
goInspectObject: (obj: SavedObjectWithMetadata) => void;

View file

@ -121,6 +121,7 @@ describe('SavedObjectsTable', () => {
};
http.post.mockResolvedValue([]);
http.delete.mockResolvedValue({ id: 'test' });
getSavedObjectCountsMock.mockReturnValue({
'index-pattern': 0,
@ -147,7 +148,7 @@ describe('SavedObjectsTable', () => {
findObjectsMock.mockImplementation(() => ({
total: 4,
savedObjects: [
saved_objects: [
{
id: '1',
type: 'index-pattern',

View file

@ -34,6 +34,7 @@ import {
SavedObjectsExportResultDetails,
getTagFindReferences,
} from '../../lib';
import { SavedObjectWithMetadata } from '../../types';
import {
SavedObjectsManagementActionServiceStart,
@ -257,7 +258,7 @@ export class SavedObjectsTable extends Component<SavedObjectsTableProps, SavedOb
}
return {
savedObjects: resp.savedObjects,
savedObjects: resp.saved_objects,
filteredItemCount: resp.total,
isSearching: false,
};

View file

@ -23,7 +23,9 @@ import {
SavedObjectsManagementColumnServiceStart,
} from './services';
import { SavedObjectManagementTypeInfo, SavedObjectGetRelationshipsResponse } from './types';
import type { v1 } from '../common';
import { SavedObjectManagementTypeInfo } from './types';
import {
getAllowedTypes,
getRelationships,
@ -46,7 +48,7 @@ export interface SavedObjectsManagementPluginStart {
type: string,
id: string,
savedObjectTypes: string[]
) => Promise<SavedObjectGetRelationshipsResponse>;
) => Promise<v1.RelationshipsResponseHTTP>;
getSavedObjectLabel: typeof getSavedObjectLabel;
getDefaultTitle: typeof getDefaultTitle;
parseQuery: typeof parseQuery;

View file

@ -12,6 +12,5 @@ export type {
SavedObjectRelationKind,
SavedObjectRelation,
SavedObjectInvalidRelation,
SavedObjectGetRelationshipsResponse,
SavedObjectManagementTypeInfo,
} from '../common';

View file

@ -9,11 +9,8 @@
import { SavedObjectsClientContract } from '@kbn/core/server';
import { injectMetaAttributes } from './inject_meta_attributes';
import { ISavedObjectsManagement } from '../services';
import {
SavedObjectInvalidRelation,
SavedObjectWithMetadata,
SavedObjectGetRelationshipsResponse,
} from '../types';
import { v1 } from '../../common';
import { SavedObjectInvalidRelation, SavedObjectWithMetadata } from '../types';
export async function findRelationships({
type,
@ -29,7 +26,7 @@ export async function findRelationships({
client: SavedObjectsClientContract;
referenceTypes: string[];
savedObjectsManagement: ISavedObjectsManagement;
}): Promise<SavedObjectGetRelationshipsResponse> {
}): Promise<v1.RelationshipsResponseHTTP> {
const { references = [] } = await client.get(type, id);
// Use a map to avoid duplicates, it does happen but have a different "name" in the reference

View file

@ -6,6 +6,7 @@
* Side Public License, v 1.
*/
export { toSavedObjectWithMeta } from './to_saved_object_with_meta';
export { injectMetaAttributes } from './inject_meta_attributes';
export { findAll } from './find_all';
export { findRelationships } from './find_relationships';

View file

@ -0,0 +1,24 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { SavedObject } from '@kbn/core/server';
import { SavedObjectWithMetadata } from '../../common/types/v1';
export function toSavedObjectWithMeta(so: SavedObject): SavedObjectWithMetadata {
return {
id: so.id,
type: so.type,
namespaces: so.namespaces,
references: so.references,
updated_at: so.updated_at,
attributes: so.attributes,
created_at: so.created_at,
error: so.error,
meta: {},
};
}

View file

@ -8,6 +8,7 @@
import { schema } from '@kbn/config-schema';
import { IRouter } from '@kbn/core/server';
import type { v1 } from '../../common';
export const registerBulkDeleteRoute = (router: IRouter) => {
router.post(
@ -29,7 +30,8 @@ export const registerBulkDeleteRoute = (router: IRouter) => {
const client = getClient();
const response = await client.bulkDelete(objects, { force: true });
return res.ok({ body: response.statuses });
const body: v1.BulkDeleteResponseHTTP = response.statuses;
return res.ok({ body });
})
);
};

View file

@ -7,9 +7,10 @@
*/
import { schema } from '@kbn/config-schema';
import { IRouter } from '@kbn/core/server';
import { injectMetaAttributes } from '../lib';
import { ISavedObjectsManagement } from '../services';
import type { IRouter } from '@kbn/core/server';
import { injectMetaAttributes, toSavedObjectWithMeta } from '../lib';
import type { v1 } from '../../common';
import type { ISavedObjectsManagement } from '../services';
export const registerBulkGetRoute = (
router: IRouter,
@ -39,14 +40,16 @@ export const registerBulkGetRoute = (
const client = getClient({ includedHiddenTypes });
const response = await client.bulkGet<unknown>(objects);
const enhancedObjects = response.saved_objects.map((obj) => {
if (!obj.error) {
const body: v1.BulkGetResponseHTTP = response.saved_objects.map((obj) => {
const so = toSavedObjectWithMeta(obj);
if (!so.error) {
return injectMetaAttributes(obj, managementService);
}
return obj;
return so;
});
return res.ok({ body: enhancedObjects });
return res.ok({ body });
})
);
};

View file

@ -7,9 +7,11 @@
*/
import { schema } from '@kbn/config-schema';
import { IRouter } from '@kbn/core/server';
import { injectMetaAttributes } from '../lib';
import { ISavedObjectsManagement } from '../services';
import type { IRouter } from '@kbn/core/server';
import type { v1 } from '../../common';
import { injectMetaAttributes, toSavedObjectWithMeta } from '../lib';
import type { ISavedObjectsManagement } from '../services';
export const registerFindRoute = (
router: IRouter,
@ -77,22 +79,23 @@ export const registerFindRoute = (
searchFields: [...searchFields],
});
const enhancedSavedObjects = findResponse.saved_objects
.map((so) => injectMetaAttributes(so, managementService))
.map((obj) => {
const result = { ...obj, attributes: {} as Record<string, any> };
const savedObjects = findResponse.saved_objects.map(toSavedObjectWithMeta);
const response: v1.FindResponseHTTP = {
saved_objects: savedObjects.map((so) => {
const obj = injectMetaAttributes(so, managementService);
const result = { ...obj, attributes: {} as Record<string, unknown> };
for (const field of includedFields) {
result.attributes[field] = obj.attributes[field];
result.attributes[field] = (obj.attributes as Record<string, unknown>)[field];
}
return result;
});
}),
total: findResponse.total,
per_page: findResponse.per_page,
page: findResponse.page,
};
return res.ok({
body: {
...findResponse,
saved_objects: enhancedSavedObjects,
},
});
return res.ok({ body: response });
})
);
};

View file

@ -6,8 +6,8 @@
* Side Public License, v 1.
*/
import { IRouter, SavedObjectsType } from '@kbn/core/server';
import { SavedObjectManagementTypeInfo } from '../../common';
import type { IRouter, SavedObjectsType } from '@kbn/core/server';
import type { SavedObjectManagementTypeInfo } from '../../common';
const convertType = (sot: SavedObjectsType): SavedObjectManagementTypeInfo => {
return {

View file

@ -7,10 +7,11 @@
*/
import { schema } from '@kbn/config-schema';
import { IRouter } from '@kbn/core/server';
import type { IRouter } from '@kbn/core/server';
import { chain } from 'lodash';
import { findRelationships } from '../lib';
import { ISavedObjectsManagement } from '../services';
import type { ISavedObjectsManagement } from '../services';
import type { v1 } from '../../common';
export const registerRelationshipsRoute = (
router: IRouter,
@ -48,7 +49,7 @@ export const registerRelationshipsRoute = (
const client = getClient({ includedHiddenTypes });
const findRelationsResponse = await findRelationships({
const findRelationsResponse: v1.RelationshipsResponseHTTP = await findRelationships({
type,
id,
client,

View file

@ -7,8 +7,9 @@
*/
import { schema } from '@kbn/config-schema';
import { IRouter, SavedObjectsCreatePointInTimeFinderOptions } from '@kbn/core/server';
import type { IRouter, SavedObjectsCreatePointInTimeFinderOptions } from '@kbn/core/server';
import { chain } from 'lodash';
import type { v1 } from '../../common';
import { findAll } from '../lib';
export const registerScrollForCountRoute = (router: IRouter) => {
@ -70,8 +71,10 @@ export const registerScrollForCountRoute = (router: IRouter) => {
}
}
const body: v1.ScrollCountResponseHTTP = counts;
return res.ok({
body: counts,
body,
});
})
);

View file

@ -18,5 +18,4 @@ export type {
SavedObjectRelationKind,
SavedObjectRelation,
SavedObjectInvalidRelation,
SavedObjectGetRelationshipsResponse,
} from '../common';

View file

@ -22,7 +22,6 @@
"@kbn/i18n-react",
"@kbn/test-jest-helpers",
"@kbn/core-saved-objects-api-server",
"@kbn/core-saved-objects-common",
"@kbn/monaco",
"@kbn/config-schema",
"@kbn/core-custom-branding-browser-mocks",

View file

@ -9,7 +9,7 @@
import { join } from 'path';
import expect from '@kbn/expect';
import type { Response } from 'supertest';
import { SavedObject } from '@kbn/core/types';
import { SavedObject } from '@kbn/core/server';
import type { SavedObjectManagementTypeInfo } from '@kbn/saved-objects-management-plugin/common/types';
import type { PluginFunctionalProviderContext } from '../../services';