mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Convert mappings to TypeScript (#32842)
* Convert mappings to TypeScript
* Use any for FieldMapping
* Revert "Use any for FieldMapping"
This reverts commit 2042601f42
.
* Use union type for FieldMapping
* Wrap toPath inside module declaration
This commit is contained in:
parent
2b606b25ed
commit
0f9779e842
18 changed files with 196 additions and 149 deletions
21
src/legacy/server/mappings/index.ts
Normal file
21
src/legacy/server/mappings/index.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { getTypes, getProperty, getRootProperties, getRootPropertiesObjects } from './lib';
|
||||
export { FieldMapping, MappingMeta, MappingProperties, IndexMapping } from './types';
|
|
@ -17,6 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { FieldMapping, IndexMapping } from '../types';
|
||||
import { getProperty } from './get_property';
|
||||
|
||||
const MAPPINGS = {
|
||||
|
@ -24,12 +25,12 @@ const MAPPINGS = {
|
|||
foo: {
|
||||
properties: {
|
||||
name: {
|
||||
type: 'text'
|
||||
type: 'text',
|
||||
},
|
||||
description: {
|
||||
type: 'text'
|
||||
}
|
||||
}
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
},
|
||||
bar: {
|
||||
properties: {
|
||||
|
@ -37,16 +38,16 @@ const MAPPINGS = {
|
|||
type: 'text',
|
||||
fields: {
|
||||
box: {
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function runTest(key, mapping) {
|
||||
function runTest(key: string | string[], mapping: IndexMapping | FieldMapping) {
|
||||
expect(typeof key === 'string' || Array.isArray(key)).toBeTruthy();
|
||||
expect(typeof mapping).toBe('object');
|
||||
|
|
@ -18,40 +18,27 @@
|
|||
*/
|
||||
|
||||
import toPath from 'lodash/internal/toPath';
|
||||
import { CoreFieldMapping, FieldMapping, IndexMapping } from '../types';
|
||||
|
||||
/**
|
||||
* Recursively read properties from the mapping object of type "object"
|
||||
* until the `path` is resolved.
|
||||
* @param {EsObjectMapping} mapping
|
||||
* @param {Array<string>} path
|
||||
* @return {Objects|undefined}
|
||||
*/
|
||||
function getPropertyMappingFromObjectMapping(mapping, path) {
|
||||
const props = mapping && (mapping.properties || mapping.fields);
|
||||
function getPropertyMappingFromObjectMapping(
|
||||
mapping: IndexMapping | FieldMapping,
|
||||
path: string[]
|
||||
): FieldMapping | undefined {
|
||||
const props =
|
||||
(mapping && (mapping as IndexMapping).properties) ||
|
||||
(mapping && (mapping as CoreFieldMapping).fields);
|
||||
|
||||
if (!props) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (path.length > 1) {
|
||||
return getPropertyMappingFromObjectMapping(
|
||||
props[path[0]],
|
||||
path.slice(1)
|
||||
);
|
||||
return getPropertyMappingFromObjectMapping(props[path[0]], path.slice(1));
|
||||
} else {
|
||||
return props[path[0]];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mapping for a specific property within the root type of the EsMappingsDsl.
|
||||
* @param {EsMappingsDsl} mappings
|
||||
* @param {string|Array<string>} path
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
export function getProperty(mappings, path) {
|
||||
return getPropertyMappingFromObjectMapping(
|
||||
mappings,
|
||||
toPath(path)
|
||||
);
|
||||
export function getProperty(mappings: IndexMapping | FieldMapping, path: string | string[]) {
|
||||
return getPropertyMappingFromObjectMapping(mappings, toPath(path));
|
||||
}
|
|
@ -17,6 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { IndexMapping } from '../types';
|
||||
|
||||
/**
|
||||
* Get the property mappings for the root type in the EsMappingsDsl
|
||||
*
|
||||
|
@ -31,14 +33,11 @@
|
|||
*
|
||||
* This data can be found at `{indexName}.mappings.{typeName}.properties`
|
||||
* in the es indices.get() response.
|
||||
*
|
||||
* @param {EsMappingsDsl} mapping
|
||||
* @return {EsPropertyMappings}
|
||||
*/
|
||||
export function getRootProperties(mapping) {
|
||||
if (mapping.type !== 'object' && !mapping.properties) {
|
||||
export function getRootProperties(mapping: IndexMapping) {
|
||||
if (!mapping.properties) {
|
||||
throw new TypeError('Unable to get property names non-object root mapping');
|
||||
}
|
||||
|
||||
return mapping.properties || {};
|
||||
return mapping.properties;
|
||||
}
|
|
@ -23,16 +23,16 @@ test(`returns single object with properties`, () => {
|
|||
const mappings = {
|
||||
properties: {
|
||||
foo: {
|
||||
properties: {}
|
||||
}
|
||||
}
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
expect(result).toEqual({
|
||||
foo: {
|
||||
properties: {}
|
||||
}
|
||||
properties: {},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -40,16 +40,16 @@ test(`returns single object with type === 'object'`, () => {
|
|||
const mappings = {
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'object'
|
||||
}
|
||||
}
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
expect(result).toEqual({
|
||||
foo: {
|
||||
type: 'object'
|
||||
}
|
||||
type: 'object',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -57,22 +57,22 @@ test(`returns two objects with properties`, () => {
|
|||
const mappings = {
|
||||
properties: {
|
||||
foo: {
|
||||
properties: {}
|
||||
properties: {},
|
||||
},
|
||||
bar: {
|
||||
properties: {}
|
||||
}
|
||||
}
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
expect(result).toEqual({
|
||||
foo: {
|
||||
properties: {}
|
||||
properties: {},
|
||||
},
|
||||
bar: {
|
||||
properties: {}
|
||||
}
|
||||
properties: {},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -80,22 +80,22 @@ test(`returns two objects with type === 'object'`, () => {
|
|||
const mappings = {
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'object'
|
||||
type: 'object',
|
||||
},
|
||||
bar: {
|
||||
type: 'object'
|
||||
}
|
||||
}
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
expect(result).toEqual({
|
||||
foo: {
|
||||
type: 'object'
|
||||
type: 'object',
|
||||
},
|
||||
bar: {
|
||||
type: 'object'
|
||||
}
|
||||
type: 'object',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -103,9 +103,9 @@ test(`excludes objects without properties and type of keyword`, () => {
|
|||
const mappings = {
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
|
@ -116,12 +116,12 @@ test(`excludes two objects without properties and type of keyword`, () => {
|
|||
const mappings = {
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'keyword'
|
||||
type: 'keyword',
|
||||
},
|
||||
bar: {
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
|
@ -132,19 +132,19 @@ test(`includes one object with properties and excludes one object without proper
|
|||
const mappings = {
|
||||
properties: {
|
||||
foo: {
|
||||
properties: {}
|
||||
properties: {},
|
||||
},
|
||||
bar: {
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
expect(result).toEqual({
|
||||
foo: {
|
||||
properties: {}
|
||||
}
|
||||
properties: {},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -152,19 +152,19 @@ test(`includes one object with type === 'object' and excludes one object without
|
|||
const mappings = {
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'object'
|
||||
type: 'object',
|
||||
},
|
||||
bar: {
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
expect(result).toEqual({
|
||||
foo: {
|
||||
type: 'object'
|
||||
}
|
||||
type: 'object',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { ComplexFieldMapping, IndexMapping, MappingProperties } from '../types';
|
||||
import { getRootProperties } from './get_root_properties';
|
||||
|
||||
/**
|
||||
|
@ -34,20 +35,21 @@ import { getRootProperties } from './get_root_properties';
|
|||
* @return {EsPropertyMappings}
|
||||
*/
|
||||
|
||||
const blacklist = [
|
||||
'migrationVersion',
|
||||
'references',
|
||||
];
|
||||
const blacklist = ['migrationVersion', 'references'];
|
||||
|
||||
export function getRootPropertiesObjects(mappings) {
|
||||
export function getRootPropertiesObjects(mappings: IndexMapping) {
|
||||
const rootProperties = getRootProperties(mappings);
|
||||
return Object.entries(rootProperties).reduce((acc, [key, value]) => {
|
||||
|
||||
// we consider the existence of the properties or type of object to designate that this is an object datatype
|
||||
if (!blacklist.includes(key) && (value.properties || value.type === 'object')) {
|
||||
acc[key] = value;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
return Object.entries(rootProperties).reduce(
|
||||
(acc, [key, value]) => {
|
||||
// we consider the existence of the properties or type of object to designate that this is an object datatype
|
||||
if (
|
||||
!blacklist.includes(key) &&
|
||||
((value as ComplexFieldMapping).properties || value.type === 'object')
|
||||
) {
|
||||
acc[key] = value;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{} as MappingProperties
|
||||
);
|
||||
}
|
|
@ -17,12 +17,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { IndexMapping } from '../types';
|
||||
|
||||
/**
|
||||
* Get the names of the types defined in the EsMappingsDsl
|
||||
*
|
||||
* @param {EsMappingsDsl} mappings
|
||||
* @return {Array<string>}
|
||||
*/
|
||||
export function getTypes(mappings) {
|
||||
export function getTypes(mappings: IndexMapping) {
|
||||
return Object.keys(mappings).filter(type => type !== '_default_');
|
||||
}
|
58
src/legacy/server/mappings/types.ts
Normal file
58
src/legacy/server/mappings/types.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
// FieldMapping isn't 1:1 with the options available,
|
||||
// modify as needed.
|
||||
export interface CoreFieldMapping {
|
||||
type: string;
|
||||
fields?: {
|
||||
[subfield: string]: {
|
||||
type: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// FieldMapping isn't 1:1 with the options available,
|
||||
// modify as needed.
|
||||
export interface ComplexFieldMapping {
|
||||
dynamic?: string;
|
||||
type?: string;
|
||||
properties: MappingProperties;
|
||||
}
|
||||
|
||||
export type FieldMapping = CoreFieldMapping | ComplexFieldMapping;
|
||||
|
||||
export interface MappingProperties {
|
||||
[field: string]: FieldMapping;
|
||||
}
|
||||
|
||||
export interface MappingMeta {
|
||||
// A dictionary of key -> md5 hash (e.g. 'dashboard': '24234qdfa3aefa3wa')
|
||||
// with each key being a root-level mapping property, and each value being
|
||||
// the md5 hash of that mapping's value when the index was created.
|
||||
migrationMappingPropertyHashes?: { [k: string]: string };
|
||||
}
|
||||
|
||||
// IndexMapping isn't 1:1 with the options available,
|
||||
// modify as needed.
|
||||
export interface IndexMapping {
|
||||
dynamic?: string;
|
||||
properties: MappingProperties;
|
||||
_meta?: MappingMeta;
|
||||
}
|
|
@ -17,8 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { IndexMapping } from './../../../mappings';
|
||||
import { buildActiveMappings, diffMappings } from './build_active_mappings';
|
||||
import { IndexMapping } from './call_cluster';
|
||||
|
||||
describe('buildActiveMappings', () => {
|
||||
test('combines all mappings and includes core mappings', () => {
|
||||
|
@ -39,7 +39,7 @@ describe('buildActiveMappings', () => {
|
|||
});
|
||||
|
||||
test('disallows mappings with leading underscore', () => {
|
||||
const properties = { _hm: 'You shall not pass!' };
|
||||
const properties = { _hm: { type: 'keyword' } };
|
||||
|
||||
expect(() => buildActiveMappings({ properties })).toThrow(
|
||||
/Invalid mapping \"_hm\"\. Mappings cannot start with _/
|
||||
|
@ -48,9 +48,9 @@ describe('buildActiveMappings', () => {
|
|||
|
||||
test('generated hashes are stable', () => {
|
||||
const properties = {
|
||||
aaa: { a: '...', b: '...', c: new Date('2019-01-02'), d: [{ hello: 'world' }] },
|
||||
bbb: { c: new Date('2019-01-02'), d: [{ hello: 'world' }], a: '...', b: '...' },
|
||||
ccc: { c: new Date('2020-01-02'), d: [{ hello: 'world' }], a: '...', b: '...' },
|
||||
aaa: { type: 'keyword', fields: { a: { type: 'keyword' }, b: { type: 'text' } } },
|
||||
bbb: { fields: { b: { type: 'text' }, a: { type: 'keyword' } }, type: 'keyword' },
|
||||
ccc: { fields: { b: { type: 'text' }, a: { type: 'text' } }, type: 'keyword' },
|
||||
};
|
||||
|
||||
const mappings = buildActiveMappings({ properties });
|
||||
|
@ -108,7 +108,7 @@ describe('diffMappings', () => {
|
|||
},
|
||||
dynamic: 'strict',
|
||||
properties: {
|
||||
foo: 'bar',
|
||||
foo: { type: 'keyword' },
|
||||
},
|
||||
};
|
||||
const expected: IndexMapping = {
|
||||
|
@ -117,7 +117,7 @@ describe('diffMappings', () => {
|
|||
},
|
||||
dynamic: 'strict',
|
||||
properties: {
|
||||
foo: 'baz',
|
||||
foo: { type: 'text' },
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
import crypto from 'crypto';
|
||||
import _ from 'lodash';
|
||||
import { IndexMapping, MappingProperties } from './call_cluster';
|
||||
import { IndexMapping, MappingProperties } from './../../../mappings';
|
||||
|
||||
/**
|
||||
* Creates an index mapping with the core properties required by saved object
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
* funcationality contained here.
|
||||
*/
|
||||
|
||||
import { IndexMapping } from '../../../mappings';
|
||||
|
||||
export interface CallCluster {
|
||||
(path: 'bulk', opts: { body: object[] }): Promise<BulkResult>;
|
||||
(path: 'count', opts: CountOpts): Promise<{ count: number; _shards: ShardsInfo }>;
|
||||
|
@ -185,20 +187,3 @@ export interface IndexInfo {
|
|||
export interface IndicesInfo {
|
||||
[index: string]: IndexInfo;
|
||||
}
|
||||
|
||||
export interface MappingProperties {
|
||||
[type: string]: any;
|
||||
}
|
||||
|
||||
export interface MappingMeta {
|
||||
// A dictionary of key -> md5 hash (e.g. 'dashboard': '24234qdfa3aefa3wa')
|
||||
// with each key being a root-level mapping property, and each value being
|
||||
// the md5 hash of that mapping's value when the index was created.
|
||||
migrationMappingPropertyHashes?: { [k: string]: string };
|
||||
}
|
||||
|
||||
export interface IndexMapping {
|
||||
dynamic: string;
|
||||
properties: MappingProperties;
|
||||
_meta?: MappingMeta;
|
||||
}
|
||||
|
|
|
@ -220,7 +220,7 @@ describe('ElasticIndex', () => {
|
|||
expect(arg.body).toEqual({
|
||||
mappings: {
|
||||
dynamic: 'strict',
|
||||
properties: { foo: 'bar' },
|
||||
properties: { foo: { type: 'keyword' } },
|
||||
},
|
||||
settings: { auto_expand_replicas: '0-1', number_of_shards: 1 },
|
||||
});
|
||||
|
@ -264,7 +264,7 @@ describe('ElasticIndex', () => {
|
|||
indexName: '.ze-index',
|
||||
mappings: {
|
||||
dynamic: 'strict',
|
||||
properties: { foo: 'bar' },
|
||||
properties: { foo: { type: 'keyword' } },
|
||||
},
|
||||
};
|
||||
await Index.convertToAlias(callCluster as any, info, '.muchacha', 10);
|
||||
|
@ -286,7 +286,7 @@ describe('ElasticIndex', () => {
|
|||
expect(arg.body).toEqual({
|
||||
mappings: {
|
||||
dynamic: 'strict',
|
||||
properties: { foo: 'bar' },
|
||||
properties: { foo: { type: 'keyword' } },
|
||||
},
|
||||
settings: { auto_expand_replicas: '0-1', number_of_shards: 1 },
|
||||
});
|
||||
|
@ -323,7 +323,7 @@ describe('ElasticIndex', () => {
|
|||
indexName: '.ze-index',
|
||||
mappings: {
|
||||
dynamic: 'strict',
|
||||
properties: { foo: 'bar' },
|
||||
properties: { foo: { type: 'keyword' } },
|
||||
},
|
||||
};
|
||||
await expect(Index.convertToAlias(callCluster as any, info, '.muchacha', 10)).rejects.toThrow(
|
||||
|
|
|
@ -23,15 +23,9 @@
|
|||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import { IndexMapping } from '../../../mappings';
|
||||
import { MigrationVersion } from '../../serialization';
|
||||
import {
|
||||
AliasAction,
|
||||
CallCluster,
|
||||
IndexMapping,
|
||||
NotFound,
|
||||
RawDoc,
|
||||
ShardsInfo,
|
||||
} from './call_cluster';
|
||||
import { AliasAction, CallCluster, NotFound, RawDoc, ShardsInfo } from './call_cluster';
|
||||
|
||||
// @ts-ignore untyped dependency
|
||||
import { getTypes } from '../../../mappings';
|
||||
|
|
|
@ -20,6 +20,6 @@
|
|||
export { DocumentMigrator } from './document_migrator';
|
||||
export { IndexMigrator } from './index_migrator';
|
||||
export { buildActiveMappings } from './build_active_mappings';
|
||||
export { CallCluster, MappingProperties } from './call_cluster';
|
||||
export { CallCluster } from './call_cluster';
|
||||
export { LogFn } from './migration_logger';
|
||||
export { MigrationResult } from './migration_coordinator';
|
||||
|
|
|
@ -25,8 +25,9 @@
|
|||
*/
|
||||
|
||||
import { SavedObjectsSerializer } from '../../serialization';
|
||||
import { MappingProperties } from './../../../mappings';
|
||||
import { buildActiveMappings } from './build_active_mappings';
|
||||
import { CallCluster, MappingProperties } from './call_cluster';
|
||||
import { CallCluster } from './call_cluster';
|
||||
import { VersionedTransformer } from './document_migrator';
|
||||
import { fetchInfo, FullIndexInfo } from './elastic_index';
|
||||
import { LogFn, Logger, MigrationLogger } from './migration_logger';
|
||||
|
|
|
@ -23,10 +23,11 @@
|
|||
*/
|
||||
|
||||
import { once } from 'lodash';
|
||||
import { MappingProperties } from '../../../mappings';
|
||||
import { SavedObjectsSchema, SavedObjectsSchemaDefinition } from '../../schema';
|
||||
import { RawSavedObjectDoc, SavedObjectsSerializer } from '../../serialization';
|
||||
import { docValidator } from '../../validation';
|
||||
import { buildActiveMappings, CallCluster, IndexMigrator, LogFn, MappingProperties } from '../core';
|
||||
import { buildActiveMappings, CallCluster, IndexMigrator, LogFn } from '../core';
|
||||
import { DocumentMigrator, VersionedTransformer } from '../core/document_migrator';
|
||||
|
||||
export interface KbnServer {
|
||||
|
|
|
@ -17,9 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export {
|
||||
getTypes,
|
||||
getProperty,
|
||||
getRootProperties,
|
||||
getRootPropertiesObjects,
|
||||
} from './lib';
|
||||
|
||||
declare module 'lodash/internal/toPath' {
|
||||
function toPath(value: string | string[]): string[]
|
||||
export = toPath;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue