mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[6.x] TypeScriptify src/utils
. (#24638)
This commit is contained in:
parent
e197a30f37
commit
f659802d96
12 changed files with 101 additions and 180 deletions
|
@ -17,12 +17,17 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export class BinderBase {
|
||||
constructor() {
|
||||
this.disposal = [];
|
||||
}
|
||||
export interface Emitter {
|
||||
on: (args: any[]) => void;
|
||||
off: (args: any[]) => void;
|
||||
addListener: Emitter['on'];
|
||||
removeListener: Emitter['off'];
|
||||
}
|
||||
|
||||
on(emitter, ...args) {
|
||||
export class BinderBase {
|
||||
private disposal: Array<() => void> = [];
|
||||
|
||||
public on(emitter: Emitter, ...args: any[]) {
|
||||
const on = emitter.on || emitter.addListener;
|
||||
const off = emitter.off || emitter.removeListener;
|
||||
|
||||
|
@ -30,7 +35,7 @@ export class BinderBase {
|
|||
this.disposal.push(() => off.apply(emitter, args));
|
||||
}
|
||||
|
||||
destroy() {
|
||||
public destroy() {
|
||||
const destroyers = this.disposal;
|
||||
this.disposal = [];
|
||||
destroyers.forEach(fn => fn());
|
|
@ -17,15 +17,14 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { BinderBase } from './binder';
|
||||
import { BinderBase, Emitter } from './binder';
|
||||
|
||||
export class BinderFor extends BinderBase {
|
||||
constructor(emitter) {
|
||||
constructor(private readonly emitter: Emitter) {
|
||||
super();
|
||||
this.emitter = emitter;
|
||||
}
|
||||
|
||||
on(...args) {
|
||||
public on(...args: any[]) {
|
||||
super.on(this.emitter, ...args);
|
||||
}
|
||||
}
|
|
@ -17,38 +17,40 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import expect from 'expect.js';
|
||||
import _ from 'lodash';
|
||||
import { keysToSnakeCaseShallow, keysToCamelCaseShallow } from '../case_conversion';
|
||||
import { keysToCamelCaseShallow, keysToSnakeCaseShallow } from './case_conversion';
|
||||
|
||||
describe('keysToSnakeCaseShallow', function () {
|
||||
|
||||
it('should convert all of an object\'s keys to snake case', function () {
|
||||
describe('keysToSnakeCaseShallow', () => {
|
||||
it("should convert all of an object's keys to snake case", () => {
|
||||
const result = keysToSnakeCaseShallow({
|
||||
camelCase: 'camel_case',
|
||||
'kebab-case': 'kebab_case',
|
||||
snake_case: 'snake_case'
|
||||
snake_case: 'snake_case',
|
||||
});
|
||||
|
||||
_.forEach(result, function (value, key) {
|
||||
expect(key).to.be(value);
|
||||
});
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"camel_case": "camel_case",
|
||||
"kebab_case": "kebab_case",
|
||||
"snake_case": "snake_case",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('keysToCamelCaseShallow', function () {
|
||||
|
||||
it('should convert all of an object\'s keys to camel case', function () {
|
||||
describe('keysToCamelCaseShallow', () => {
|
||||
it("should convert all of an object's keys to camel case", () => {
|
||||
const result = keysToCamelCaseShallow({
|
||||
camelCase: 'camelCase',
|
||||
'kebab-case': 'kebabCase',
|
||||
snake_case: 'snakeCase'
|
||||
snake_case: 'snakeCase',
|
||||
});
|
||||
|
||||
_.forEach(result, function (value, key) {
|
||||
expect(key).to.be(value);
|
||||
});
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"camelCase": "camelCase",
|
||||
"kebabCase": "kebabCase",
|
||||
"snakeCase": "snakeCase",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
});
|
|
@ -19,13 +19,13 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
|
||||
export function keysToSnakeCaseShallow(object) {
|
||||
export function keysToSnakeCaseShallow(object: Record<string, any>) {
|
||||
return _.mapKeys(object, (value, key) => {
|
||||
return _.snakeCase(key);
|
||||
});
|
||||
}
|
||||
|
||||
export function keysToCamelCaseShallow(object) {
|
||||
export function keysToCamelCaseShallow(object: Record<string, any>) {
|
||||
return _.mapKeys(object, (value, key) => {
|
||||
return _.camelCase(key);
|
||||
});
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
const set = Symbol('internal set');
|
||||
|
||||
export default class Collection {
|
||||
constructor() { // Set's have a length of 0, mimic that
|
||||
this[set] = new Set(arguments[0] || []);
|
||||
}
|
||||
|
||||
/******
|
||||
** Collection API
|
||||
******/
|
||||
|
||||
toArray() {
|
||||
return [...this.values()];
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return this.toArray();
|
||||
}
|
||||
|
||||
/******
|
||||
** ES Set Api
|
||||
******/
|
||||
|
||||
static get [Symbol.species]() {
|
||||
return Collection;
|
||||
}
|
||||
|
||||
get size() {
|
||||
return this[set].size;
|
||||
}
|
||||
|
||||
add(value) {
|
||||
return this[set].add(value);
|
||||
}
|
||||
|
||||
clear() {
|
||||
return this[set].clear();
|
||||
}
|
||||
|
||||
delete(value) {
|
||||
return this[set].delete(value);
|
||||
}
|
||||
|
||||
entries() {
|
||||
return this[set].entries();
|
||||
}
|
||||
|
||||
forEach(callbackFn, thisArg) {
|
||||
return this[set].forEach(callbackFn, thisArg);
|
||||
}
|
||||
|
||||
has(value) {
|
||||
return this[set].has(value);
|
||||
}
|
||||
|
||||
keys() {
|
||||
return this[set].keys();
|
||||
}
|
||||
|
||||
values() {
|
||||
return this[set].values();
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this[set][Symbol.iterator]();
|
||||
}
|
||||
}
|
|
@ -17,64 +17,63 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { deepCloneWithBuffers } from '../deep_clone_with_buffers';
|
||||
import expect from 'expect.js';
|
||||
import { deepCloneWithBuffers } from './deep_clone_with_buffers';
|
||||
|
||||
describe('deepCloneWithBuffers()', function () {
|
||||
it('deep clones objects', function () {
|
||||
describe('deepCloneWithBuffers()', () => {
|
||||
it('deep clones objects', () => {
|
||||
const source = {
|
||||
a: {
|
||||
b: {},
|
||||
c: {},
|
||||
d: [
|
||||
{
|
||||
e: 'f'
|
||||
}
|
||||
]
|
||||
}
|
||||
e: 'f',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const output = deepCloneWithBuffers(source);
|
||||
|
||||
expect(source.a).to.eql(output.a);
|
||||
expect(source.a).to.not.be(output.a);
|
||||
expect(source.a).toEqual(output.a);
|
||||
expect(source.a).not.toBe(output.a);
|
||||
|
||||
expect(source.a.b).to.eql(output.a.b);
|
||||
expect(source.a.b).to.not.be(output.a.b);
|
||||
expect(source.a.b).toEqual(output.a.b);
|
||||
expect(source.a.b).not.toBe(output.a.b);
|
||||
|
||||
expect(source.a.c).to.eql(output.a.c);
|
||||
expect(source.a.c).to.not.be(output.a.c);
|
||||
expect(source.a.c).toEqual(output.a.c);
|
||||
expect(source.a.c).not.toBe(output.a.c);
|
||||
|
||||
expect(source.a.d).to.eql(output.a.d);
|
||||
expect(source.a.d).to.not.be(output.a.d);
|
||||
expect(source.a.d).toEqual(output.a.d);
|
||||
expect(source.a.d).not.toBe(output.a.d);
|
||||
|
||||
expect(source.a.d[0]).to.eql(output.a.d[0]);
|
||||
expect(source.a.d[0]).to.not.be(output.a.d[0]);
|
||||
expect(source.a.d[0]).toEqual(output.a.d[0]);
|
||||
expect(source.a.d[0]).not.toBe(output.a.d[0]);
|
||||
});
|
||||
|
||||
it('copies buffers but keeps them buffers', function () {
|
||||
it('copies buffers but keeps them buffers', () => {
|
||||
const input = new Buffer('i am a teapot', 'utf8');
|
||||
const output = deepCloneWithBuffers(input);
|
||||
|
||||
expect(Buffer.isBuffer(input)).to.be.ok();
|
||||
expect(Buffer.isBuffer(output)).to.be.ok();
|
||||
expect(Buffer.isBuffer(input)).toBe(true);
|
||||
expect(Buffer.isBuffer(output)).toBe(true);
|
||||
expect(Buffer.compare(output, input));
|
||||
expect(output).to.not.be(input);
|
||||
expect(output).not.toBe(input);
|
||||
});
|
||||
|
||||
it('copies buffers that are deep', function () {
|
||||
it('copies buffers that are deep', () => {
|
||||
const input = {
|
||||
a: {
|
||||
b: {
|
||||
c: new Buffer('i am a teapot', 'utf8')
|
||||
}
|
||||
}
|
||||
c: new Buffer('i am a teapot', 'utf8'),
|
||||
},
|
||||
},
|
||||
};
|
||||
const output = deepCloneWithBuffers(input);
|
||||
|
||||
expect(Buffer.isBuffer(input.a.b.c)).to.be.ok();
|
||||
expect(Buffer.isBuffer(output.a.b.c)).to.be.ok();
|
||||
expect(Buffer.isBuffer(input.a.b.c)).toBe(true);
|
||||
expect(Buffer.isBuffer(output.a.b.c)).toBe(true);
|
||||
expect(Buffer.compare(output.a.b.c, input.a.b.c));
|
||||
expect(output.a.b.c).to.not.be(input.a.b.c);
|
||||
expect(output.a.b.c).not.toBe(input.a.b.c);
|
||||
});
|
||||
});
|
|
@ -19,12 +19,15 @@
|
|||
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
function cloneBuffersCustomizer(val) {
|
||||
// We should add `any` return type to overcome bug in lodash types, customizer
|
||||
// in lodash 3.* can return `undefined` if cloning is handled by the lodash, but
|
||||
// type of the customizer function doesn't expect that.
|
||||
function cloneBuffersCustomizer(val: unknown): any {
|
||||
if (Buffer.isBuffer(val)) {
|
||||
return new Buffer(val);
|
||||
}
|
||||
}
|
||||
|
||||
export function deepCloneWithBuffers(vals) {
|
||||
return cloneDeep(vals, cloneBuffersCustomizer);
|
||||
export function deepCloneWithBuffers<T>(val: T): T {
|
||||
return cloneDeep(val, cloneBuffersCustomizer);
|
||||
}
|
|
@ -28,11 +28,11 @@
|
|||
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
||||
* / "*" / "+" / "," / ";" / "="
|
||||
*/
|
||||
export function encodeQueryComponent(val, pctEncodeSpaces = false) {
|
||||
export function encodeQueryComponent(val: string, pctEncodeSpaces = false) {
|
||||
return encodeURIComponent(val)
|
||||
.replace(/%40/gi, '@')
|
||||
.replace(/%3A/gi, ':')
|
||||
.replace(/%24/g, '$')
|
||||
.replace(/%2C/gi, ',')
|
||||
.replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
|
||||
.replace(/%20/g, pctEncodeSpaces ? '%20' : '+');
|
||||
}
|
|
@ -17,9 +17,9 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { pkg } from './package_json';
|
||||
import { resolve } from 'path';
|
||||
import { pkg } from './package_json';
|
||||
|
||||
export function fromRoot(...args) {
|
||||
export function fromRoot(...args: string[]) {
|
||||
return resolve(pkg.__dirname, ...args);
|
||||
}
|
|
@ -17,29 +17,30 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import expect from 'expect.js';
|
||||
|
||||
import { getFlattenedObject } from '../get_flattened_object';
|
||||
import { getFlattenedObject } from './get_flattened_object';
|
||||
|
||||
describe('getFlattenedObject()', () => {
|
||||
it('throws when rootValue is not an object or is an array', () => {
|
||||
expect(() => getFlattenedObject(1)).to.throwError('number');
|
||||
expect(() => getFlattenedObject(Infinity)).to.throwError('number');
|
||||
expect(() => getFlattenedObject(NaN)).to.throwError('number');
|
||||
expect(() => getFlattenedObject(false)).to.throwError('boolean');
|
||||
expect(() => getFlattenedObject(null)).to.throwError('null');
|
||||
expect(() => getFlattenedObject(undefined)).to.throwError('undefined');
|
||||
expect(() => getFlattenedObject([])).to.throwError('array');
|
||||
expect(() => getFlattenedObject(1)).toThrowError();
|
||||
expect(() => getFlattenedObject(Infinity)).toThrowError();
|
||||
expect(() => getFlattenedObject(NaN)).toThrowError();
|
||||
expect(() => getFlattenedObject(false)).toThrowError();
|
||||
expect(() => getFlattenedObject(null)).toThrowError();
|
||||
expect(() => getFlattenedObject(undefined)).toThrowError();
|
||||
expect(() => getFlattenedObject([])).toThrowError();
|
||||
});
|
||||
|
||||
it('flattens objects', () => {
|
||||
expect(getFlattenedObject({ a: 'b' })).to.eql({ a: 'b' });
|
||||
expect(getFlattenedObject({ a: { b: 'c' } })).to.eql({ 'a.b': 'c' });
|
||||
expect(getFlattenedObject({ a: { b: 'c' }, d: { e: 'f' } })).to.eql({ 'a.b': 'c', 'd.e': 'f' });
|
||||
expect(getFlattenedObject({ a: 'b' })).toEqual({ a: 'b' });
|
||||
expect(getFlattenedObject({ a: { b: 'c' } })).toEqual({ 'a.b': 'c' });
|
||||
expect(getFlattenedObject({ a: { b: 'c' }, d: { e: 'f' } })).toEqual({
|
||||
'a.b': 'c',
|
||||
'd.e': 'f',
|
||||
});
|
||||
});
|
||||
|
||||
it('does not flatten arrays', () => {
|
||||
expect(getFlattenedObject({ a: ['b'] })).to.eql({ a: ['b'] });
|
||||
expect(getFlattenedObject({ a: { b: ['c', 'd'] } })).to.eql({ 'a.b': ['c', 'd'] });
|
||||
expect(getFlattenedObject({ a: ['b'] })).toEqual({ a: ['b'] });
|
||||
expect(getFlattenedObject({ a: { b: ['c', 'd'] } })).toEqual({ 'a.b': ['c', 'd'] });
|
||||
});
|
||||
});
|
|
@ -17,8 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
function shouldReadKeys(value) {
|
||||
function shouldReadKeys(value: unknown): value is Record<string, any> {
|
||||
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
||||
}
|
||||
|
||||
|
@ -34,21 +33,21 @@ function shouldReadKeys(value) {
|
|||
* @param {Object} rootValue
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function getFlattenedObject(rootValue) {
|
||||
export function getFlattenedObject(rootValue: unknown) {
|
||||
if (!shouldReadKeys(rootValue)) {
|
||||
throw new TypeError(`Root value is not flatten-able, received ${rootValue}`);
|
||||
}
|
||||
|
||||
return (function flatten(acc, prefix, object) {
|
||||
return Object.keys(object).reduce((acc, key) => {
|
||||
const value = object[key];
|
||||
return (function flatten<T extends Record<string, any>>(acc: T, prefix: string, object: T): T {
|
||||
for (const [key, value] of Object.entries(object)) {
|
||||
const path = prefix ? `${prefix}.${key}` : key;
|
||||
|
||||
if (shouldReadKeys(value)) {
|
||||
return flatten(acc, path, value);
|
||||
flatten(acc, path, value);
|
||||
} else {
|
||||
return { ...acc, [path]: value };
|
||||
acc[path] = value;
|
||||
}
|
||||
}, acc);
|
||||
}({}, '', rootValue));
|
||||
}
|
||||
|
||||
return acc;
|
||||
})({}, '', rootValue);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue