diff --git a/packages/core/src/common/utils/__tests__/iter.test.ts b/packages/core/src/common/utils/__tests__/iter.test.ts index 2489649d90..db9c61793d 100644 --- a/packages/core/src/common/utils/__tests__/iter.test.ts +++ b/packages/core/src/common/utils/__tests__/iter.test.ts @@ -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", () => { diff --git a/packages/core/src/common/utils/array.ts b/packages/core/src/common/utils/array.ts deleted file mode 100644 index b9071c33ec..0000000000 --- a/packages/core/src/common/utils/array.ts +++ /dev/null @@ -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(length: number, value: T): T[] { - return Array(length).fill(value); -} diff --git a/packages/core/src/common/utils/autobind.ts b/packages/core/src/common/utils/autobind.ts deleted file mode 100644 index 49feb435e3..0000000000 --- a/packages/core/src/common/utils/autobind.ts +++ /dev/null @@ -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(obj: T, opts?: Options): T { - if (obj instanceof React.Component) { - return autoBindReactClass(obj, opts); - } - - return autoBindClass(obj, opts); -} diff --git a/packages/core/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts b/packages/core/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts index 34f62d51d5..d6db37cea2 100644 --- a/packages/core/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts +++ b/packages/core/src/common/utils/channel/enlist-message-channel-listener-injection-token.ts @@ -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>) => Disposer; diff --git a/packages/core/src/common/utils/escapeRegExp.ts b/packages/core/src/common/utils/escapeRegExp.ts deleted file mode 100644 index 9d5c7e2ff6..0000000000 --- a/packages/core/src/common/utils/escapeRegExp.ts +++ /dev/null @@ -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 -} diff --git a/packages/core/src/common/utils/getRandId.ts b/packages/core/src/common/utils/getRandId.ts deleted file mode 100644 index 489456d56b..0000000000 --- a/packages/core/src/common/utils/getRandId.ts +++ /dev/null @@ -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); -} diff --git a/packages/core/src/common/utils/index.ts b/packages/core/src/common/utils/index.ts index 4857d04418..d95bd52904 100644 --- a/packages/core/src/common/utils/index.ts +++ b/packages/core/src/common/utils/index.ts @@ -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, -}; diff --git a/packages/core/src/common/utils/is-promise/is-promise.test.ts b/packages/core/src/common/utils/is-promise/is-promise.test.ts deleted file mode 100644 index 565f272ed6..0000000000 --- a/packages/core/src/common/utils/is-promise/is-promise.test.ts +++ /dev/null @@ -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); - }); -}); diff --git a/packages/core/src/common/utils/is-promise/is-promise.ts b/packages/core/src/common/utils/is-promise/is-promise.ts deleted file mode 100644 index 6261f569cd..0000000000 --- a/packages/core/src/common/utils/is-promise/is-promise.ts +++ /dev/null @@ -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 { - return reference?.constructor === Promise; -} diff --git a/packages/core/src/common/utils/json.ts b/packages/core/src/common/utils/json.ts deleted file mode 100644 index 53d357f05c..0000000000 --- a/packages/core/src/common/utils/json.ts +++ /dev/null @@ -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); -} diff --git a/packages/core/src/common/utils/n-fircate.ts b/packages/core/src/common/utils/n-fircate.ts deleted file mode 100644 index 0f195adc10..0000000000 --- a/packages/core/src/common/utils/n-fircate.ts +++ /dev/null @@ -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(from: Iterable, field: keyof T, parts: []): []; -export function nFircate(from: Iterable, field: keyof T, parts: [T[typeof field]]): [T[]]; -export function nFircate(from: Iterable, field: keyof T, parts: [T[typeof field], T[typeof field]]): [T[], T[]]; -export function nFircate(from: Iterable, field: keyof T, parts: [T[typeof field], T[typeof field], T[typeof field]]): [T[], T[], T[]]; - -export function nFircate(from: Iterable, 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; -} diff --git a/packages/core/src/common/utils/promise-exec.ts b/packages/core/src/common/utils/promise-exec.ts deleted file mode 100644 index e2471d2611..0000000000 --- a/packages/core/src/common/utils/promise-exec.ts +++ /dev/null @@ -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); diff --git a/packages/core/src/common/utils/with-error-logging/with-error-logging.injectable.ts b/packages/core/src/common/utils/with-error-logging/with-error-logging.injectable.ts index 0aaca9f97d..37bf7220c7 100644 --- a/packages/core/src/common/utils/with-error-logging/with-error-logging.injectable.ts +++ b/packages/core/src/common/utils/with-error-logging/with-error-logging.injectable.ts @@ -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); diff --git a/packages/core/src/common/utils/with-error-suppression/with-error-suppression.ts b/packages/core/src/common/utils/with-error-suppression/with-error-suppression.ts index 657ed13c16..22d51b6014 100644 --- a/packages/core/src/common/utils/with-error-suppression/with-error-suppression.ts +++ b/packages/core/src/common/utils/with-error-suppression/with-error-suppression.ts @@ -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 { - return !!reference?.then; -} diff --git a/packages/core/src/renderer/utils/index.ts b/packages/core/src/renderer/utils/index.ts deleted file mode 100755 index cde1a70077..0000000000 --- a/packages/core/src/renderer/utils/index.ts +++ /dev/null @@ -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"; diff --git a/packages/utility-features/utilities/README.md b/packages/utility-features/utilities/README.md new file mode 100644 index 0000000000..336b802f84 --- /dev/null +++ b/packages/utility-features/utilities/README.md @@ -0,0 +1,3 @@ +# @k8slens/utilities + +This package contains many useful types. diff --git a/packages/utility-features/utilities/index.ts b/packages/utility-features/utilities/index.ts new file mode 100644 index 0000000000..ab2940d092 --- /dev/null +++ b/packages/utility-features/utilities/index.ts @@ -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"; diff --git a/packages/utility-features/utilities/jest.config.js b/packages/utility-features/utilities/jest.config.js new file mode 100644 index 0000000000..23be80353b --- /dev/null +++ b/packages/utility-features/utilities/jest.config.js @@ -0,0 +1,2 @@ +module.exports = + require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; diff --git a/packages/utility-features/utilities/package.json b/packages/utility-features/utilities/package.json new file mode 100644 index 0000000000..78ac7085e9 --- /dev/null +++ b/packages/utility-features/utilities/package.json @@ -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" + } +} diff --git a/packages/core/src/common/utils/abort-controller.ts b/packages/utility-features/utilities/src/abort-controller.ts similarity index 100% rename from packages/core/src/common/utils/abort-controller.ts rename to packages/utility-features/utilities/src/abort-controller.ts diff --git a/packages/core/src/common/utils/splitArray.ts b/packages/utility-features/utilities/src/array.ts similarity index 54% rename from packages/core/src/common/utils/splitArray.ts rename to packages/utility-features/utilities/src/array.ts index 142d4a33ff..c2fe54f3c9 100644 --- a/packages/core/src/common/utils/splitArray.ts +++ b/packages/utility-features/utilities/src/array.ts @@ -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(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(array: T[], element: T): [T[], T[], boolean] { - const index = array.indexOf(element); +export function split(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(src: T[], condition: (item: T) => boolean): [falses: T[], trues: T[]] { - const res: [T[], T[]] = [[], []]; +export function bifurcate(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]; } diff --git a/packages/core/src/common/utils/backoff-caller.ts b/packages/utility-features/utilities/src/backoff-caller.ts similarity index 96% rename from packages/core/src/common/utils/backoff-caller.ts rename to packages/utility-features/utilities/src/backoff-caller.ts index 131565bb09..148ff4cd25 100644 --- a/packages/core/src/common/utils/backoff-caller.ts +++ b/packages/utility-features/utilities/src/backoff-caller.ts @@ -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 diff --git a/packages/core/src/common/utils/base64.ts b/packages/utility-features/utilities/src/base64.ts similarity index 100% rename from packages/core/src/common/utils/base64.ts rename to packages/utility-features/utilities/src/base64.ts diff --git a/packages/core/src/common/utils/camelCase.ts b/packages/utility-features/utilities/src/camelCase.ts similarity index 96% rename from packages/core/src/common/utils/camelCase.ts rename to packages/utility-features/utilities/src/camelCase.ts index a37e4c7f5c..1055c46ffb 100644 --- a/packages/core/src/common/utils/camelCase.ts +++ b/packages/utility-features/utilities/src/camelCase.ts @@ -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[]>(obj: T): T; export function toCamelCase>(obj: T): T; diff --git a/packages/core/src/common/utils/collection-functions.ts b/packages/utility-features/utilities/src/collection-functions.ts similarity index 94% rename from packages/core/src/common/utils/collection-functions.ts rename to packages/utility-features/utilities/src/collection-functions.ts index 5d6dc80548..e78e215e8b 100644 --- a/packages/core/src/common/utils/collection-functions.ts +++ b/packages/utility-features/utilities/src/collection-functions.ts @@ -19,7 +19,6 @@ export function getOrInsert(map: Map, 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(map: Map | WeakMap(map: Map, 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)!; } diff --git a/packages/core/src/common/utils/computed-or.ts b/packages/utility-features/utilities/src/computed-or.ts similarity index 100% rename from packages/core/src/common/utils/computed-or.ts rename to packages/utility-features/utilities/src/computed-or.ts diff --git a/packages/core/src/common/utils/convertCpu.ts b/packages/utility-features/utilities/src/convertCpu.ts similarity index 100% rename from packages/core/src/common/utils/convertCpu.ts rename to packages/utility-features/utilities/src/convertCpu.ts diff --git a/packages/core/src/common/utils/convertMemory.ts b/packages/utility-features/utilities/src/convertMemory.ts similarity index 97% rename from packages/core/src/common/utils/convertMemory.ts rename to packages/utility-features/utilities/src/convertMemory.ts index 7cae1cf0c1..c9df572b19 100644 --- a/packages/core/src/common/utils/convertMemory.ts +++ b/packages/utility-features/utilities/src/convertMemory.ts @@ -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 diff --git a/packages/core/src/renderer/utils/cssNames.ts b/packages/utility-features/utilities/src/cssNames.ts similarity index 77% rename from packages/core/src/renderer/utils/cssNames.ts rename to packages/utility-features/utilities/src/cssNames.ts index aebf5cdf72..66731c45bd 100755 --- a/packages/core/src/renderer/utils/cssNames.ts +++ b/packages/utility-features/utilities/src/cssNames.ts @@ -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 | 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(" "); } diff --git a/packages/core/src/renderer/utils/cssVar.ts b/packages/utility-features/utilities/src/cssVar.ts similarity index 100% rename from packages/core/src/renderer/utils/cssVar.ts rename to packages/utility-features/utilities/src/cssVar.ts diff --git a/packages/core/src/common/utils/debouncePromise.ts b/packages/utility-features/utilities/src/debouncePromise.ts similarity index 85% rename from packages/core/src/common/utils/debouncePromise.ts rename to packages/utility-features/utilities/src/debouncePromise.ts index c15b206a76..1610b977b2 100755 --- a/packages/core/src/common/utils/debouncePromise.ts +++ b/packages/utility-features/utilities/src/debouncePromise.ts @@ -10,6 +10,6 @@ export function debouncePromise(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); }); } diff --git a/packages/core/src/common/utils/delay.ts b/packages/utility-features/utilities/src/delay.ts similarity index 100% rename from packages/core/src/common/utils/delay.ts rename to packages/utility-features/utilities/src/delay.ts diff --git a/packages/core/src/renderer/utils/display-mode.ts b/packages/utility-features/utilities/src/display-mode.ts similarity index 100% rename from packages/core/src/renderer/utils/display-mode.ts rename to packages/utility-features/utilities/src/display-mode.ts diff --git a/packages/core/src/common/utils/disposer.ts b/packages/utility-features/utilities/src/disposer.ts similarity index 91% rename from packages/core/src/common/utils/disposer.ts rename to packages/utility-features/utilities/src/disposer.ts index 2949a7ae35..f7be4dc34d 100644 --- a/packages/core/src/common/utils/disposer.ts +++ b/packages/utility-features/utilities/src/disposer.ts @@ -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[]): ExtendableDisposer { diff --git a/packages/core/src/common/utils/formatDuration.ts b/packages/utility-features/utilities/src/formatDuration.ts similarity index 100% rename from packages/core/src/common/utils/formatDuration.ts rename to packages/utility-features/utilities/src/formatDuration.ts diff --git a/packages/core/src/common/utils/hash-set.ts b/packages/utility-features/utilities/src/hash-set.ts similarity index 100% rename from packages/core/src/common/utils/hash-set.ts rename to packages/utility-features/utilities/src/hash-set.ts diff --git a/packages/core/src/renderer/utils/interval.ts b/packages/utility-features/utilities/src/interval.ts similarity index 100% rename from packages/core/src/renderer/utils/interval.ts rename to packages/utility-features/utilities/src/interval.ts diff --git a/packages/core/src/renderer/utils/is-node-falsy.ts b/packages/utility-features/utilities/src/is-node-falsy.ts similarity index 100% rename from packages/core/src/renderer/utils/is-node-falsy.ts rename to packages/utility-features/utilities/src/is-node-falsy.ts diff --git a/packages/core/src/renderer/utils/isMiddleClick.ts b/packages/utility-features/utilities/src/isMiddleClick.ts similarity index 100% rename from packages/core/src/renderer/utils/isMiddleClick.ts rename to packages/utility-features/utilities/src/isMiddleClick.ts diff --git a/packages/core/src/renderer/utils/isReactNode.ts b/packages/utility-features/utilities/src/isReactNode.ts similarity index 100% rename from packages/core/src/renderer/utils/isReactNode.ts rename to packages/utility-features/utilities/src/isReactNode.ts diff --git a/packages/core/src/common/utils/iter.ts b/packages/utility-features/utilities/src/iter.ts similarity index 79% rename from packages/core/src/common/utils/iter.ts rename to packages/utility-features/utilities/src/iter.ts index dc1c4621fd..4da7855959 100644 --- a/packages/core/src/common/utils/iter.ts +++ b/packages/utility-features/utilities/src/iter.ts @@ -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 extends Iterable { filter(fn: (val: T) => unknown): Iterator; - filterMap(fn: (val: T) => Falsey | U): Iterator; + filterMap(fn: (val: T) => Falsy | U): Iterator; find(fn: (val: T) => unknown): T | undefined; collect(fn: (values: Iterable) => U): U; map(fn: (val: T) => U): Iterator; @@ -67,11 +67,11 @@ export function* map(src: Iterable, 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(src: Iterable, fn: (from: T) => Iterable | Falsey): IterableIterator { +export function* filterFlatMap(src: Iterable, fn: (from: T) => Iterable | Falsy): IterableIterator { for (const from of src) { if (!from) { continue; @@ -122,7 +122,7 @@ export function* filter(src: Iterable, 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(src: Iterable, fn: (from: T) => U | Falsey): IterableIterator { +export function* filterMap(src: Iterable, fn: (from: T) => U | Falsy): IterableIterator { for (const from of src) { const res = fn(from); @@ -166,9 +166,9 @@ export function find(src: Iterable, 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>(src: Iterable, reducer: (acc: R, cur: T) => R, initial: R): R; @@ -224,7 +224,7 @@ export function first(src: Iterable): 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(...sources: IterableIterator[]): 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(from: Iterable, field: keyof T, parts: []): []; +export function nFircate(from: Iterable, field: keyof T, parts: [T[typeof field]]): [T[]]; +export function nFircate(from: Iterable, field: keyof T, parts: [T[typeof field], T[typeof field]]): [T[], T[]]; +export function nFircate(from: Iterable, field: keyof T, parts: [T[typeof field], T[typeof field], T[typeof field]]): [T[], T[], T[]]; + +export function nFircate(from: Iterable, 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; +} diff --git a/packages/utility-features/utilities/src/json.ts b/packages/utility-features/utilities/src/json.ts new file mode 100644 index 0000000000..1c8d051ac3 --- /dev/null +++ b/packages/utility-features/utilities/src/json.ts @@ -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 => { + try { + return { + callWasSuccessful: true, + response: JSON.parse(input) as unknown, + } + } catch (error) { + return { + callWasSuccessful: false, + error: error as Error, + } + } + }, +}; diff --git a/packages/core/src/renderer/utils/jsonPath.ts b/packages/utility-features/utilities/src/jsonPath.ts similarity index 100% rename from packages/core/src/renderer/utils/jsonPath.ts rename to packages/utility-features/utilities/src/jsonPath.ts diff --git a/packages/core/src/renderer/utils/metricUnitsToNumber.ts b/packages/utility-features/utilities/src/metricUnitsToNumber.ts similarity index 100% rename from packages/core/src/renderer/utils/metricUnitsToNumber.ts rename to packages/utility-features/utilities/src/metricUnitsToNumber.ts diff --git a/packages/core/src/renderer/utils/name-parts.ts b/packages/utility-features/utilities/src/name-parts.ts similarity index 100% rename from packages/core/src/renderer/utils/name-parts.ts rename to packages/utility-features/utilities/src/name-parts.ts diff --git a/packages/core/src/common/utils/noop.ts b/packages/utility-features/utilities/src/noop.ts similarity index 99% rename from packages/core/src/common/utils/noop.ts rename to packages/utility-features/utilities/src/noop.ts index a9171f2618..b985da1930 100644 --- a/packages/core/src/common/utils/noop.ts +++ b/packages/utility-features/utilities/src/noop.ts @@ -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(...args: T): void { return void args; } + diff --git a/packages/core/src/common/utils/objects.ts b/packages/utility-features/utilities/src/object.ts similarity index 99% rename from packages/core/src/common/utils/objects.ts rename to packages/utility-features/utilities/src/object.ts index 9b6355d3e7..b5836af6ea 100644 --- a/packages/core/src/common/utils/objects.ts +++ b/packages/utility-features/utilities/src/object.ts @@ -12,7 +12,6 @@ export function fromEntries(entries: Iterable(obj: Partial>): K[]; - export function keys(obj: Record): K[] { return Object.keys(obj) as K[]; } @@ -20,7 +19,6 @@ export function keys(obj: Record): K[] { export function entries(obj: Partial> | null | undefined): [K, V][]; export function entries(obj: Partial> | null | undefined): [K, V][]; export function entries(obj: Record | null | undefined): [K, V][]; - export function entries(obj: Record | null | undefined): [K, V][] { if (obj && typeof obj == "object") { return Object.entries(obj) as never; diff --git a/packages/core/src/common/utils/observable-crate/observable-crate.test.ts b/packages/utility-features/utilities/src/observable-crate.test.ts similarity index 96% rename from packages/core/src/common/utils/observable-crate/observable-crate.test.ts rename to packages/utility-features/utilities/src/observable-crate.test.ts index 03ee2e43f8..acadb804cc 100644 --- a/packages/core/src/common/utils/observable-crate/observable-crate.test.ts +++ b/packages/utility-features/utilities/src/observable-crate.test.ts @@ -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", () => { diff --git a/packages/core/src/common/utils/observable-crate/impl.ts b/packages/utility-features/utilities/src/observable-crate.ts similarity index 93% rename from packages/core/src/common/utils/observable-crate/impl.ts rename to packages/utility-features/utilities/src/observable-crate.ts index e9874c9b7d..d7cd1b75bb 100644 --- a/packages/core/src/common/utils/observable-crate/impl.ts +++ b/packages/utility-features/utilities/src/observable-crate.ts @@ -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 { get(): T; diff --git a/packages/core/src/renderer/utils/on-keyboard-shortcut.ts b/packages/utility-features/utilities/src/on-keyboard-shortcut.ts similarity index 100% rename from packages/core/src/renderer/utils/on-keyboard-shortcut.ts rename to packages/utility-features/utilities/src/on-keyboard-shortcut.ts diff --git a/packages/core/src/renderer/utils/prevDefault.ts b/packages/utility-features/utilities/src/prevDefault.ts similarity index 100% rename from packages/core/src/renderer/utils/prevDefault.ts rename to packages/utility-features/utilities/src/prevDefault.ts diff --git a/packages/core/src/common/utils/readableStream.ts b/packages/utility-features/utilities/src/readableStream.ts similarity index 100% rename from packages/core/src/common/utils/readableStream.ts rename to packages/utility-features/utilities/src/readableStream.ts diff --git a/packages/core/src/common/utils/readonly.ts b/packages/utility-features/utilities/src/readonly.ts similarity index 100% rename from packages/core/src/common/utils/readonly.ts rename to packages/utility-features/utilities/src/readonly.ts diff --git a/packages/core/src/common/utils/reject-promise.ts b/packages/utility-features/utilities/src/reject-promise.ts similarity index 100% rename from packages/core/src/common/utils/reject-promise.ts rename to packages/utility-features/utilities/src/reject-promise.ts diff --git a/packages/core/src/common/utils/async-result.ts b/packages/utility-features/utilities/src/result.ts similarity index 51% rename from packages/core/src/common/utils/async-result.ts rename to packages/utility-features/utilities/src/result.ts index 69927f3275..b0153d46d4 100644 --- a/packages/core/src/common/utils/async-result.ts +++ b/packages/utility-features/utilities/src/result.ts @@ -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 = + +/** + * A helper type for async functions that return a `Result` + */ +export type AsyncResult = Promise>; + +/** + * Result describes the "error is just more data" pattern instead of using exceptions for + * normal execution + */ +export type Result = | ( Response extends void ? { callWasSuccessful: true; response?: undefined } diff --git a/packages/core/src/common/utils/sort-compare.ts b/packages/utility-features/utilities/src/sort-compare.ts similarity index 100% rename from packages/core/src/common/utils/sort-compare.ts rename to packages/utility-features/utilities/src/sort-compare.ts diff --git a/packages/core/src/common/utils/sort-function.ts b/packages/utility-features/utilities/src/sort-function.ts similarity index 100% rename from packages/core/src/common/utils/sort-function.ts rename to packages/utility-features/utilities/src/sort-function.ts diff --git a/packages/core/src/common/utils/tar.ts b/packages/utility-features/utilities/src/tar.ts similarity index 94% rename from packages/core/src/common/utils/tar.ts rename to packages/utility-features/utilities/src/tar.ts index 3102098976..701cd66fd8 100644 --- a/packages/core/src/common/utils/tar.ts +++ b/packages/utility-features/utilities/src/tar.ts @@ -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 = { @@ -43,7 +42,7 @@ export function readFileFromTar({ 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); }); diff --git a/packages/core/src/common/utils/tuple.ts b/packages/utility-features/utilities/src/tuple.ts similarity index 97% rename from packages/core/src/common/utils/tuple.ts rename to packages/utility-features/utilities/src/tuple.ts index 1268678617..a9ad662e52 100644 --- a/packages/core/src/common/utils/tuple.ts +++ b/packages/utility-features/utilities/src/tuple.ts @@ -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 diff --git a/packages/core/src/common/utils/type-narrowing.ts b/packages/utility-features/utilities/src/type-narrowing.ts similarity index 100% rename from packages/core/src/common/utils/type-narrowing.ts rename to packages/utility-features/utilities/src/type-narrowing.ts diff --git a/packages/core/src/common/utils/types.ts b/packages/utility-features/utilities/src/types.ts similarity index 93% rename from packages/core/src/common/utils/types.ts rename to packages/utility-features/utilities/src/types.ts index 32ebe14e33..25d665b811 100644 --- a/packages/core/src/common/utils/types.ts +++ b/packages/utility-features/utilities/src/types.ts @@ -14,7 +14,7 @@ export type RemoveUndefinedFromValues = { */ export type Defaulted = RemoveUndefinedFromValues>> & Omit; -export type OptionVarient = { +export type OptionVariant = { type: Key; } & Pick & { [OtherKey in Exclude]?: undefined; diff --git a/packages/core/src/common/utils/union-env-path.ts b/packages/utility-features/utilities/src/union-env-path.ts similarity index 84% rename from packages/core/src/common/utils/union-env-path.ts rename to packages/utility-features/utilities/src/union-env-path.ts index 991e2c776c..a3a6d39ed6 100644 --- a/packages/core/src/common/utils/union-env-path.ts +++ b/packages/utility-features/utilities/src/union-env-path.ts @@ -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 diff --git a/packages/core/src/common/utils/wait.ts b/packages/utility-features/utilities/src/wait.ts similarity index 95% rename from packages/core/src/common/utils/wait.ts rename to packages/utility-features/utilities/src/wait.ts index 402d556b5d..8f10b1d039 100644 --- a/packages/core/src/common/utils/wait.ts +++ b/packages/utility-features/utilities/src/wait.ts @@ -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(getter: (() => T | null | undefined) | IComputedValue, opts?: { timeout?: number }): Promise { return new Promise((resolve, reject) => { diff --git a/packages/core/src/common/utils/with-concurrency-limit.ts b/packages/utility-features/utilities/src/with-concurrency-limit.ts similarity index 86% rename from packages/core/src/common/utils/with-concurrency-limit.ts rename to packages/utility-features/utilities/src/with-concurrency-limit.ts index 284bb334e1..43c083c2dd 100644 --- a/packages/core/src/common/utils/with-concurrency-limit.ts +++ b/packages/utility-features/utilities/src/with-concurrency-limit.ts @@ -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 = (fn: (...args: Args) => Res) => (...args: Args) => Promise; export function withConcurrencyLimit(limit: number): ConcurrencyLimiter { - const limiter = plimit(limit); + const limiter = pLimit(limit); return fn => (...args) => limiter(() => fn(...args)); } diff --git a/packages/utility-features/utilities/tsconfig.json b/packages/utility-features/utilities/tsconfig.json new file mode 100644 index 0000000000..a4f6fa613e --- /dev/null +++ b/packages/utility-features/utilities/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@k8slens/typescript/config/base.json" +} diff --git a/packages/utility-features/utilities/webpack.config.js b/packages/utility-features/utilities/webpack.config.js new file mode 100644 index 0000000000..3183f30179 --- /dev/null +++ b/packages/utility-features/utilities/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForNode;