mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Move all utility functions to separate package
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
83950f46ce
commit
13673eaac4
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { join, nth, reduce, concat } from "../iter";
|
||||
import { join, nth, reduce, concat } from "@k8slens/utilities/src/iter";
|
||||
|
||||
describe("iter", () => {
|
||||
describe("reduce", () => {
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A inference typed version of `Array(length).fill(value)`
|
||||
* @param length The number of entries
|
||||
* @param value The value of each of the indices
|
||||
*/
|
||||
export function filled<T>(length: number, value: T): T[] {
|
||||
return Array(length).fill(value);
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { Options } from "auto-bind";
|
||||
import autoBindClass from "auto-bind";
|
||||
import autoBindReactClass from "auto-bind/react";
|
||||
import React from "react";
|
||||
|
||||
// Automatically bind methods to their class instance
|
||||
export function autoBind<T extends object>(obj: T, opts?: Options): T {
|
||||
if (obj instanceof React.Component) {
|
||||
return autoBindReactClass(obj, opts);
|
||||
}
|
||||
|
||||
return autoBindClass(obj, opts);
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { Disposer } from "../disposer";
|
||||
import type { Disposer } from "@k8slens/utilities";
|
||||
import type { MessageChannel, MessageChannelListener } from "./message-channel-listener-injection-token";
|
||||
|
||||
export type EnlistMessageChannelListener = (listener: MessageChannelListener<MessageChannel<unknown>>) => Disposer;
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
// Helper to sanitize / escape special chars for passing to RegExp-constructor
|
||||
|
||||
export function escapeRegExp(str: string) {
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
// Create random system name
|
||||
|
||||
export function getRandId({ prefix = "", suffix = "", sep = "_" } = {}) {
|
||||
const randId = () => Math.random().toString(16).slice(2);
|
||||
|
||||
return [prefix, randId(), suffix].filter(s => s).join(sep);
|
||||
}
|
||||
@ -3,50 +3,5 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
export * from "./abort-controller";
|
||||
export * from "./autobind";
|
||||
export * from "./camelCase";
|
||||
export * from "./cluster-id-url-parsing";
|
||||
export * from "./collection-functions";
|
||||
export * from "./convertCpu";
|
||||
export * from "./convertMemory";
|
||||
export * from "./debouncePromise";
|
||||
export * from "./delay";
|
||||
export * from "./disposer";
|
||||
export * from "./escapeRegExp";
|
||||
export * from "./formatDuration";
|
||||
export * from "./getRandId";
|
||||
export * from "./hash-set";
|
||||
export * from "./n-fircate";
|
||||
export * from "./noop";
|
||||
export * from "./observable-crate/impl";
|
||||
export * from "./promise-exec";
|
||||
export * from "./readonly";
|
||||
export * from "./reject-promise";
|
||||
export * from "./singleton";
|
||||
export * from "./sort-compare";
|
||||
export * from "./splitArray";
|
||||
export * from "./tar";
|
||||
export * from "./toJS";
|
||||
export * from "./type-narrowing";
|
||||
export * from "./types";
|
||||
export * from "./wait-for-path";
|
||||
export * from "./wait";
|
||||
|
||||
export type { Tuple } from "./tuple";
|
||||
|
||||
import * as iter from "./iter";
|
||||
import * as array from "./array";
|
||||
import * as tuple from "./tuple";
|
||||
import * as base64 from "./base64";
|
||||
import * as object from "./objects";
|
||||
import * as json from "./json";
|
||||
|
||||
export {
|
||||
iter,
|
||||
array,
|
||||
tuple,
|
||||
base64,
|
||||
object,
|
||||
json,
|
||||
};
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { isPromise } from "./is-promise";
|
||||
|
||||
describe("isPromise", () => {
|
||||
it("given promise, returns true", () => {
|
||||
const actual = isPromise(new Promise(() => {}));
|
||||
|
||||
expect(actual).toBe(true);
|
||||
});
|
||||
|
||||
it("given non-promise, returns false", () => {
|
||||
const actual = isPromise({});
|
||||
|
||||
expect(actual).toBe(false);
|
||||
});
|
||||
|
||||
it("given thenable, returns false", () => {
|
||||
const actual = isPromise({ then: () => {} });
|
||||
|
||||
expect(actual).toBe(false);
|
||||
});
|
||||
|
||||
it("given nothing, returns false", () => {
|
||||
const actual = isPromise(undefined);
|
||||
|
||||
expect(actual).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -1,7 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
export function isPromise(reference: any): reference is Promise<any> {
|
||||
return reference?.constructor === Promise;
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { JsonValue } from "type-fest";
|
||||
|
||||
export function parse(input: string): JsonValue {
|
||||
return JSON.parse(input);
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Split an iterable into several arrays with matching fields
|
||||
* @param from The iterable of items to split up
|
||||
* @param field The field of each item to split over
|
||||
* @param parts What each array will be filtered to
|
||||
* @returns A `parts.length` tuple of `T[]` where each array has matching `field` values
|
||||
*/
|
||||
export function nFircate<T>(from: Iterable<T>, field: keyof T, parts: []): [];
|
||||
export function nFircate<T>(from: Iterable<T>, field: keyof T, parts: [T[typeof field]]): [T[]];
|
||||
export function nFircate<T>(from: Iterable<T>, field: keyof T, parts: [T[typeof field], T[typeof field]]): [T[], T[]];
|
||||
export function nFircate<T>(from: Iterable<T>, field: keyof T, parts: [T[typeof field], T[typeof field], T[typeof field]]): [T[], T[], T[]];
|
||||
|
||||
export function nFircate<T>(from: Iterable<T>, field: keyof T, parts: T[typeof field][]): T[][] {
|
||||
if (new Set(parts).size !== parts.length) {
|
||||
throw new TypeError("Duplicate parts entries");
|
||||
}
|
||||
|
||||
const res = Array.from(parts, () => [] as T[]);
|
||||
|
||||
for (const item of from) {
|
||||
const index = parts.indexOf(item[field]);
|
||||
|
||||
if (index < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
res[index].push(item);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import * as util from "util";
|
||||
import { execFile } from "child_process";
|
||||
|
||||
export const promiseExecFile = util.promisify(execFile);
|
||||
@ -4,7 +4,6 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import logErrorInjectable from "../../log-error.injectable";
|
||||
import { isPromise } from "../is-promise/is-promise";
|
||||
|
||||
export type WithErrorLoggingFor = (
|
||||
getErrorMessage: (error: unknown) => string
|
||||
@ -33,7 +32,7 @@ const withErrorLoggingInjectable = getInjectable({
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (isPromise(returnValue)) {
|
||||
if ((returnValue as any) instanceof Promise) {
|
||||
return returnValue.catch((e: unknown) => {
|
||||
const errorMessage = getErrorMessage(e);
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ export function withErrorSuppression(toBeDecorated: any) {
|
||||
try {
|
||||
const returnValue = toBeDecorated(...args);
|
||||
|
||||
if (isPromise(returnValue)) {
|
||||
if ((returnValue as any) instanceof Promise) {
|
||||
return returnValue.catch(noop);
|
||||
}
|
||||
|
||||
@ -22,7 +22,3 @@ export function withErrorSuppression(toBeDecorated: any) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function isPromise(reference: any): reference is Promise<any> {
|
||||
return !!reference?.then;
|
||||
}
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
// Common usage utils & helpers
|
||||
export * from "../../common/utils";
|
||||
export * from "../../common/event-emitter";
|
||||
|
||||
export * from "./cssNames";
|
||||
export * from "./cssVar";
|
||||
export * from "./display-mode";
|
||||
export * from "./interval";
|
||||
export * from "./isMiddleClick";
|
||||
export * from "./isReactNode";
|
||||
export * from "./metricUnitsToNumber";
|
||||
export * from "./name-parts";
|
||||
export * from "./prevDefault";
|
||||
export * from "./saveFile";
|
||||
export * from "./storage-helper";
|
||||
3
packages/utility-features/utilities/README.md
Normal file
3
packages/utility-features/utilities/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# @k8slens/utilities
|
||||
|
||||
This package contains many useful types.
|
||||
45
packages/utility-features/utilities/index.ts
Normal file
45
packages/utility-features/utilities/index.ts
Normal file
@ -0,0 +1,45 @@
|
||||
export * from "./src/abort-controller";
|
||||
export * from "./src/backoff-caller";
|
||||
export * from "./src/camelCase";
|
||||
export * from "./src/collection-functions";
|
||||
export * from "./src/computed-or";
|
||||
export * from "./src/convertCpu";
|
||||
export * from "./src/convertMemory";
|
||||
export * from "./src/cssNames";
|
||||
export * from "./src/cssVar";
|
||||
export * from "./src/debouncePromise";
|
||||
export * from "./src/delay";
|
||||
export * from "./src/display-mode";
|
||||
export * from "./src/disposer";
|
||||
export * from "./src/formatDuration";
|
||||
export * from "./src/hash-set";
|
||||
export * from "./src/interval";
|
||||
export * from "./src/is-node-falsy";
|
||||
export * from "./src/isMiddleClick";
|
||||
export * from "./src/isReactNode";
|
||||
export * from "./src/json";
|
||||
export * from "./src/jsonPath";
|
||||
export * from "./src/metricUnitsToNumber";
|
||||
export * from "./src/name-parts";
|
||||
export * from "./src/noop";
|
||||
export * from "./src/observable-crate";
|
||||
export * from "./src/on-keyboard-shortcut";
|
||||
export * from "./src/prevDefault";
|
||||
export * from "./src/readableStream";
|
||||
export * from "./src/readonly";
|
||||
export * from "./src/reject-promise";
|
||||
export * from "./src/result";
|
||||
export * from "./src/sort-compare";
|
||||
export * from "./src/sort-function";
|
||||
export * from "./src/tar";
|
||||
export * from "./src/tuple";
|
||||
export * from "./src/type-narrowing";
|
||||
export * from "./src/types";
|
||||
export * from "./src/union-env-path";
|
||||
export * from "./src/wait";
|
||||
export * from "./src/with-concurrency-limit";
|
||||
|
||||
export * as iter from "./src/iter";
|
||||
export * as array from "./src/array";
|
||||
export * as object from "./src/object";
|
||||
export * as base64 from "./src/base64";
|
||||
2
packages/utility-features/utilities/jest.config.js
Normal file
2
packages/utility-features/utilities/jest.config.js
Normal file
@ -0,0 +1,2 @@
|
||||
module.exports =
|
||||
require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact;
|
||||
31
packages/utility-features/utilities/package.json
Normal file
31
packages/utility-features/utilities/package.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "@k8slens/utilities",
|
||||
"description": "A collection of useful types",
|
||||
"version": "1.0.0",
|
||||
"type": "commonjs",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"private": false,
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"author": {
|
||||
"name": "OpenLens Authors",
|
||||
"email": "info@k8slens.dev"
|
||||
},
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/lensapp/lens",
|
||||
"scripts": {
|
||||
"build": "webpack",
|
||||
"dev": "webpack --mode=development --watch",
|
||||
"test": "jest --coverage --runInBand"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"mobx": "^6.8.0",
|
||||
"type-fest": "^2.19.0"
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,15 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A inference typed version of `Array(length).fill(value)`
|
||||
* @param length The number of entries
|
||||
* @param value The value of each of the indices
|
||||
*/
|
||||
export function filled<T>(length: number, value: T): T[] {
|
||||
return Array(length).fill(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function splits an array into two sub arrays on the first instance of
|
||||
* element (from the left). If the array does not contain the element. The
|
||||
@ -14,29 +23,27 @@
|
||||
* @returns the left and right sub-arrays which when conjoined with `element`
|
||||
* is the same as `array`, and `true`
|
||||
*/
|
||||
export function splitArray<T>(array: T[], element: T): [T[], T[], boolean] {
|
||||
const index = array.indexOf(element);
|
||||
export function split<T>(src: T[], element: T): [T[], T[], boolean] {
|
||||
const index = src.indexOf(element);
|
||||
|
||||
if (index < 0) {
|
||||
return [array, [], false];
|
||||
return [src, [], false];
|
||||
}
|
||||
|
||||
return [array.slice(0, index), array.slice(index + 1, array.length), true];
|
||||
return [src.slice(0, index), src.slice(index + 1, src.length), true];
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits an array into two parts based on the outcome of `condition`. If `true`
|
||||
* the value will be returned as part of the right array. If `false` then part of
|
||||
* the left array.
|
||||
* @param src the full array to bifurcate
|
||||
* @param condition the function to determine which set each is in
|
||||
*/
|
||||
export function bifurcateArray<T>(src: T[], condition: (item: T) => boolean): [falses: T[], trues: T[]] {
|
||||
const res: [T[], T[]] = [[], []];
|
||||
export function bifurcate<T>(src: T[], condition: (item: T) => any): [falses: T[], trues: T[]] {
|
||||
const trues: T[] = [];
|
||||
const falses: T[] = [];
|
||||
|
||||
for (const item of src) {
|
||||
res[+condition(item)].push(item);
|
||||
if (condition(item)) {
|
||||
trues.push(item);
|
||||
} else {
|
||||
falses.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
return [falses, trues];
|
||||
}
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
import type { AsyncResult } from "./async-result";
|
||||
import { delay } from "./delay";
|
||||
import { noop } from "./noop";
|
||||
import { noop } from "@k8slens/utilities/src/noop";
|
||||
|
||||
/**
|
||||
* @param error The error that resulted in the failure
|
||||
@ -7,7 +7,7 @@
|
||||
import { camelCase } from "lodash";
|
||||
import type { SingleOrMany } from "./types";
|
||||
import { isObject, isString } from "./type-narrowing";
|
||||
import * as object from "./objects";
|
||||
import * as object from "./object";
|
||||
|
||||
export function toCamelCase<T extends Record<string, unknown>[]>(obj: T): T;
|
||||
export function toCamelCase<T extends Record<string, unknown>>(obj: T): T;
|
||||
@ -19,7 +19,6 @@ export function getOrInsert<K, V>(map: Map<K, V>, key: K, value: V): V {
|
||||
map.set(key, value);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return map.get(key)!;
|
||||
}
|
||||
|
||||
@ -67,7 +66,6 @@ export function getOrInsertWith<K extends object, V>(map: Map<K, V> | WeakMap<K,
|
||||
map.set(key, builder());
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return map.get(key)!;
|
||||
}
|
||||
|
||||
@ -107,7 +105,6 @@ export function strictGet<K, V>(map: Map<K, V>, key: K): V {
|
||||
throw new TypeError(`Map does not contains key: ${inspect(key)}`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return map.get(key)!;
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import assert from "assert";
|
||||
import * as iter from "./iter";
|
||||
import { iter } from "@k8slens/utilities";
|
||||
|
||||
// Helper to convert memory from units Ki, Mi, Gi, Ti, Pi to bytes and vise versa
|
||||
|
||||
@ -3,7 +3,9 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { iter } from "../../common/utils";
|
||||
import * as iter from "./iter";
|
||||
import * as object from "./object";
|
||||
import { isObject } from "./type-narrowing";
|
||||
|
||||
export type IgnoredClassNames = number | symbol | Function;
|
||||
export type IClassName = string | string[] | Record<string, any> | undefined | null | false | IgnoredClassNames;
|
||||
@ -18,15 +20,15 @@ export function cssNames(...classNames: IClassName[]): string {
|
||||
for (const name of className) {
|
||||
classNamesEnabled.set(name, true);
|
||||
}
|
||||
} else if (className && typeof className === "object") {
|
||||
for (const [name, value] of Object.entries(className)) {
|
||||
} else if (isObject(className)) {
|
||||
for (const [name, value] of object.entries(className)) {
|
||||
classNamesEnabled.set(name, Boolean(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return iter.chain(classNamesEnabled.entries())
|
||||
.filter(([, isActive]) => !!isActive)
|
||||
.filter(([, isActive]) => isActive)
|
||||
.filterMap(([className]) => className.trim())
|
||||
.join(" ");
|
||||
}
|
||||
@ -10,6 +10,6 @@ export function debouncePromise<T, F extends any[]>(func: (...args: F) => T | Pr
|
||||
|
||||
return (...params: F) => new Promise(resolve => {
|
||||
clearTimeout(timer);
|
||||
timer = global.setTimeout(() => resolve(func(...params)), timeout);
|
||||
timer = setTimeout(() => resolve(func(...params)), timeout);
|
||||
});
|
||||
}
|
||||
@ -5,8 +5,6 @@
|
||||
|
||||
import type { SingleOrMany } from "./types";
|
||||
|
||||
|
||||
|
||||
export interface Disposer {
|
||||
(): void;
|
||||
}
|
||||
@ -16,7 +14,7 @@ export interface Disposable {
|
||||
}
|
||||
|
||||
export interface ExtendableDisposer extends Disposer {
|
||||
push(...vals: (Disposer | ExtendableDisposer | Disposable)[]): void;
|
||||
push(...values: (Disposer | ExtendableDisposer | Disposable)[]): void;
|
||||
}
|
||||
|
||||
export function disposer(...items: SingleOrMany<Disposer | Disposable | undefined | null>[]): ExtendableDisposer {
|
||||
@ -3,11 +3,11 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
export type Falsey = false | 0 | "" | null | undefined;
|
||||
export type Falsy = false | 0 | "" | null | undefined;
|
||||
|
||||
interface Iterator<T> extends Iterable<T> {
|
||||
filter(fn: (val: T) => unknown): Iterator<T>;
|
||||
filterMap<U>(fn: (val: T) => Falsey | U): Iterator<U>;
|
||||
filterMap<U>(fn: (val: T) => Falsy | U): Iterator<U>;
|
||||
find(fn: (val: T) => unknown): T | undefined;
|
||||
collect<U>(fn: (values: Iterable<T>) => U): U;
|
||||
map<U>(fn: (val: T) => U): Iterator<U>;
|
||||
@ -67,11 +67,11 @@ export function* map<T, U>(src: Iterable<T>, fn: (from: T) => U): IterableIterat
|
||||
}
|
||||
|
||||
/**
|
||||
* The single layer flattening of an iterator, discarding `Falsey` values.
|
||||
* The single layer flattening of an iterator, discarding `Falsy` values.
|
||||
* @param src A type that can be iterated over
|
||||
* @param fn The function that returns either an iterable over items that should be filtered out or a `Falsey` value indicating that it should be ignored
|
||||
* @param fn The function that returns either an iterable over items that should be filtered out or a `Falsy` value indicating that it should be ignored
|
||||
*/
|
||||
export function* filterFlatMap<T, U>(src: Iterable<T>, fn: (from: T) => Iterable<U | Falsey> | Falsey): IterableIterator<U> {
|
||||
export function* filterFlatMap<T, U>(src: Iterable<T>, fn: (from: T) => Iterable<U | Falsy> | Falsy): IterableIterator<U> {
|
||||
for (const from of src) {
|
||||
if (!from) {
|
||||
continue;
|
||||
@ -122,7 +122,7 @@ export function* filter<T>(src: Iterable<T>, fn: (from: T) => any): IterableIter
|
||||
* @param src A type that can be iterated over
|
||||
* @param fn The function that is called for each value
|
||||
*/
|
||||
export function* filterMap<T, U>(src: Iterable<T>, fn: (from: T) => U | Falsey): IterableIterator<U> {
|
||||
export function* filterMap<T, U>(src: Iterable<T>, fn: (from: T) => U | Falsy): IterableIterator<U> {
|
||||
for (const from of src) {
|
||||
const res = fn(from);
|
||||
|
||||
@ -166,9 +166,9 @@ export function find<T>(src: Iterable<T>, match: (i: T) => any): T | undefined {
|
||||
|
||||
/**
|
||||
* Iterate over `src` calling `reducer` with the previous produced value and the current
|
||||
* yielded value until `src` is exausted. Then return the final value.
|
||||
* yielded value until `src` is exhausted. Then return the final value.
|
||||
* @param src The value to iterate over
|
||||
* @param reducer A function for producing the next item from an accumilation and the current item
|
||||
* @param reducer A function for producing the next item from an accumulation and the current item
|
||||
* @param initial The initial value for the iteration
|
||||
*/
|
||||
export function reduce<T, R extends Iterable<any>>(src: Iterable<T>, reducer: (acc: R, cur: T) => R, initial: R): R;
|
||||
@ -224,7 +224,7 @@ export function first<T>(src: Iterable<T>): T | undefined {
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through `src` and return `true` if `fn` returns a thruthy value for every yielded value.
|
||||
* Iterate through `src` and return `true` if `fn` returns a truthy value for every yielded value.
|
||||
* Otherwise, return `false`. This function short circuits.
|
||||
* @param src The type to be iterated over
|
||||
* @param fn A function to check each iteration
|
||||
@ -246,3 +246,35 @@ export function* concat<T>(...sources: IterableIterator<T>[]): IterableIterator<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Split an iterable into several arrays with matching fields
|
||||
* @param from The iterable of items to split up
|
||||
* @param field The field of each item to split over
|
||||
* @param parts What each array will be filtered to
|
||||
* @returns A `parts.length` tuple of `T[]` where each array has matching `field` values
|
||||
*/
|
||||
export function nFircate<T>(from: Iterable<T>, field: keyof T, parts: []): [];
|
||||
export function nFircate<T>(from: Iterable<T>, field: keyof T, parts: [T[typeof field]]): [T[]];
|
||||
export function nFircate<T>(from: Iterable<T>, field: keyof T, parts: [T[typeof field], T[typeof field]]): [T[], T[]];
|
||||
export function nFircate<T>(from: Iterable<T>, field: keyof T, parts: [T[typeof field], T[typeof field], T[typeof field]]): [T[], T[], T[]];
|
||||
|
||||
export function nFircate<T>(from: Iterable<T>, field: keyof T, parts: T[typeof field][]): T[][] {
|
||||
if (new Set(parts).size !== parts.length) {
|
||||
throw new TypeError("Duplicate parts entries");
|
||||
}
|
||||
|
||||
const res = Array.from(parts, () => [] as T[]);
|
||||
|
||||
for (const item of from) {
|
||||
const index = parts.indexOf(item[field]);
|
||||
|
||||
if (index < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
res[index].push(item);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
22
packages/utility-features/utilities/src/json.ts
Normal file
22
packages/utility-features/utilities/src/json.ts
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { Result } from "./result";
|
||||
|
||||
export const json = {
|
||||
parse: (input: string): Result<unknown, Error> => {
|
||||
try {
|
||||
return {
|
||||
callWasSuccessful: true,
|
||||
response: JSON.parse(input) as unknown,
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
error: error as Error,
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -2,9 +2,11 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A function that does nothing
|
||||
*/
|
||||
export function noop<T extends any[]>(...args: T): void {
|
||||
return void args;
|
||||
}
|
||||
|
||||
@ -12,7 +12,6 @@ export function fromEntries<T, Key extends string>(entries: Iterable<readonly [K
|
||||
}
|
||||
|
||||
export function keys<K extends keyof any>(obj: Partial<Record<K, any>>): K[];
|
||||
|
||||
export function keys<K extends keyof any>(obj: Record<K, any>): K[] {
|
||||
return Object.keys(obj) as K[];
|
||||
}
|
||||
@ -20,7 +19,6 @@ export function keys<K extends keyof any>(obj: Record<K, any>): K[] {
|
||||
export function entries<K extends string, V>(obj: Partial<Record<K, V>> | null | undefined): [K, V][];
|
||||
export function entries<K extends string | number | symbol, V>(obj: Partial<Record<K, V>> | null | undefined): [K, V][];
|
||||
export function entries<K extends string | number | symbol, V>(obj: Record<K, V> | null | undefined): [K, V][];
|
||||
|
||||
export function entries<K extends string | number | symbol, V>(obj: Record<K, V> | null | undefined): [K, V][] {
|
||||
if (obj && typeof obj == "object") {
|
||||
return Object.entries(obj) as never;
|
||||
@ -3,8 +3,8 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { ObservableCrate } from "./impl";
|
||||
import { observableCrate } from "./impl";
|
||||
import type { ObservableCrate } from "./observable-crate";
|
||||
import { observableCrate } from "./observable-crate";
|
||||
|
||||
describe("observable-crate", () => {
|
||||
it("can be constructed with initial value", () => {
|
||||
@ -4,8 +4,8 @@
|
||||
*/
|
||||
|
||||
import { observable, runInAction } from "mobx";
|
||||
import { getOrInsertMap } from "../collection-functions";
|
||||
import { noop } from "../noop";
|
||||
import { getOrInsertMap } from "./collection-functions";
|
||||
import { noop } from "./noop";
|
||||
|
||||
export interface ObservableCrate<T> {
|
||||
get(): T;
|
||||
@ -2,7 +2,17 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
export type AsyncResult<Response, Error = string> =
|
||||
|
||||
/**
|
||||
* A helper type for async functions that return a `Result`
|
||||
*/
|
||||
export type AsyncResult<Response, Error = string> = Promise<Result<Response, Error>>;
|
||||
|
||||
/**
|
||||
* Result describes the "error is just more data" pattern instead of using exceptions for
|
||||
* normal execution
|
||||
*/
|
||||
export type Result<Response, Error = string> =
|
||||
| (
|
||||
Response extends void
|
||||
? { callWasSuccessful: true; response?: undefined }
|
||||
@ -7,7 +7,6 @@
|
||||
// Docs: https://github.com/npm/node-tar
|
||||
import tar from "tar";
|
||||
import path from "path";
|
||||
import { parse } from "./json";
|
||||
import type { JsonValue } from "type-fest";
|
||||
|
||||
export type ReadFileFromTarOpts<ParseJson extends boolean> = {
|
||||
@ -43,7 +42,7 @@ export function readFileFromTar<ParseJson extends boolean>({ tarPath, filePath,
|
||||
});
|
||||
entry.once("end", () => {
|
||||
const data = Buffer.concat(fileChunks);
|
||||
const result = parseJson ? parse(data.toString("utf8")) : data;
|
||||
const result = parseJson ? JSON.parse(data.toString("utf8")) : data;
|
||||
|
||||
resolve(result);
|
||||
});
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import * as array from "../utils/array";
|
||||
import * as array from "./array";
|
||||
|
||||
/**
|
||||
* A strict N-tuple of type T
|
||||
@ -14,7 +14,7 @@ export type RemoveUndefinedFromValues<K> = {
|
||||
*/
|
||||
export type Defaulted<Params, DefaultParams extends keyof Params> = RemoveUndefinedFromValues<Required<Pick<Params, DefaultParams>>> & Omit<Params, DefaultParams>;
|
||||
|
||||
export type OptionVarient<Key, Base, RequiredKey extends keyof Base> = {
|
||||
export type OptionVariant<Key, Base, RequiredKey extends keyof Base> = {
|
||||
type: Key;
|
||||
} & Pick<Base, RequiredKey> & {
|
||||
[OtherKey in Exclude<keyof Base, RequiredKey>]?: undefined;
|
||||
@ -4,10 +4,10 @@
|
||||
*/
|
||||
|
||||
import path from "path";
|
||||
import * as iter from "./iter";
|
||||
import * as iter from "@k8slens/utilities/src/iter";
|
||||
|
||||
/**
|
||||
* Join all entires with a PATH env var delimated string together
|
||||
* Join all entires with a PATH env var delimited string together
|
||||
* @param PATHs Any number of PATH env variables
|
||||
*
|
||||
* NOTE: This function does not attempt to handle any sort of escape sequences since after testing
|
||||
@ -4,7 +4,7 @@
|
||||
*/
|
||||
import type { IComputedValue } from "mobx";
|
||||
import { runInAction, when } from "mobx";
|
||||
import type { Disposer } from "./disposer";
|
||||
import type { Disposer } from "@k8slens/utilities";
|
||||
|
||||
export async function waitUntilDefined<T>(getter: (() => T | null | undefined) | IComputedValue<T | null | undefined>, opts?: { timeout?: number }): Promise<T> {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
@ -2,12 +2,12 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import plimit from "p-limit";
|
||||
import pLimit from "p-limit";
|
||||
|
||||
export type ConcurrencyLimiter = <Args extends any[], Res>(fn: (...args: Args) => Res) => (...args: Args) => Promise<Res>;
|
||||
|
||||
export function withConcurrencyLimit(limit: number): ConcurrencyLimiter {
|
||||
const limiter = plimit(limit);
|
||||
const limiter = pLimit(limit);
|
||||
|
||||
return fn => (...args) => limiter(() => fn(...args));
|
||||
}
|
||||
3
packages/utility-features/utilities/tsconfig.json
Normal file
3
packages/utility-features/utilities/tsconfig.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "@k8slens/typescript/config/base.json"
|
||||
}
|
||||
1
packages/utility-features/utilities/webpack.config.js
Normal file
1
packages/utility-features/utilities/webpack.config.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require("@k8slens/webpack").configForNode;
|
||||
Loading…
Reference in New Issue
Block a user