@starbeam/core-utils
Advanced tools
Comparing version 0.8.10-unstable.9203102 to 0.8.10-unstable.0ad7df5
{ | ||
"root": false, | ||
"overrides": [ | ||
{ | ||
"extends": ["plugin:@starbeam/tight"], | ||
"files": ["index.ts", "src/**/*.ts"], | ||
"parserOptions": { | ||
"project": "tsconfig.json" | ||
} | ||
} | ||
] | ||
"root": true, | ||
"extends": ["plugin:@starbeam-dev/library:recommended"] | ||
} |
18
index.ts
export { | ||
FIRST_OFFSET, | ||
firstNItems, | ||
@@ -9,4 +10,7 @@ getFirst, | ||
isEmptyArray, | ||
isEmptyCollection, | ||
isPresentArray, | ||
isPresentCollection, | ||
isSingleItemArray, | ||
LAST_OFFSET, | ||
mapArray, | ||
@@ -26,14 +30,2 @@ mapIfPresent, | ||
export { type UnknownFn } from "./src/function.js"; | ||
export { | ||
DisplayStruct, | ||
type DisplayStructOptions, | ||
} from "./src/inspect/display-struct.js"; | ||
export { | ||
DEBUG, | ||
DEBUG_NAME, | ||
INSPECT, | ||
type Inspect, | ||
inspect, | ||
inspector, | ||
} from "./src/inspect/inspect-support.js"; | ||
export { iterableHasItems, reverse } from "./src/iterable.js"; | ||
@@ -52,2 +44,3 @@ export type { | ||
defMethod, | ||
type Expand, | ||
getter, | ||
@@ -67,2 +60,3 @@ isObject, | ||
} from "./src/string.js"; | ||
export { exhaustive } from "./src/types.js"; | ||
export { isPresent } from "./src/value.js"; |
{ | ||
"name": "@starbeam/core-utils", | ||
"version": "0.8.10-unstable.9203102", | ||
"type": "module", | ||
"main": "index.ts", | ||
"types": "index.ts", | ||
"version": "0.8.10-unstable.0ad7df5", | ||
"main": "dist/index.cjs", | ||
"types": "dist/index.d.ts", | ||
"exports": { | ||
"default": "./index.ts" | ||
"types": "./dist/index.d.ts", | ||
"import": "./dist/index.js", | ||
"default": "./dist/index.cjs" | ||
}, | ||
"publishConfig": { | ||
"exports": { | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"import": "./dist/index.js", | ||
"default": "./dist/index.cjs" | ||
} | ||
}, | ||
"main": "dist/index.cjs", | ||
"types": "dist/index.d.ts" | ||
"starbeam": { | ||
"type": "library:public" | ||
}, | ||
"starbeam:type": "library:public", | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"@starbeam-dev/compile": "^1.0.2", | ||
"@starbeam-dev/eslint-plugin": "^1.0.4", | ||
"rollup": "^4.0.2" | ||
}, | ||
"scripts": { | ||
"test:lint": "eslint \"index.ts\" \"src/**/*.ts\"", | ||
"test:specs": "vitest --run", | ||
"test:lint": "eslint . --max-warnings 0", | ||
"test:specs": "vitest --run --pool forks", | ||
"test:types": "tsc -b" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"@starbeam-dev/build-support": "workspace:*", | ||
"rollup": "^3.20.6" | ||
} | ||
} | ||
} |
163
src/array.ts
@@ -0,1 +1,3 @@ | ||
/* eslint-disable @typescript-eslint/no-magic-numbers -- this file absorbs magic | ||
numbers for the rest of the codebase */ | ||
const EMPTY_LENGTH = 0; | ||
@@ -6,2 +8,3 @@ | ||
export type PresentArray<T> = MutablePresentArray<T> | ReadonlyPresentArray<T>; | ||
export type ArrayItem<T> = T extends unknown[] ? T[number] : never; | ||
@@ -11,3 +14,5 @@ export type AnyArray<T> = T[] | readonly T[]; | ||
type PresentArrayFor<T extends unknown[] | readonly unknown[] | undefined> = | ||
T extends readonly (infer Item)[] | (infer Item)[] | ||
T extends (infer Item)[] | ||
? [Item, ...Item[]] | ||
: T extends readonly (infer Item)[] | ||
? readonly [Item, ...Item[]] | ||
@@ -17,3 +22,3 @@ : never; | ||
export function isPresentArray< | ||
T extends unknown[] | readonly unknown[] | undefined | ||
T extends unknown[] | readonly unknown[] | undefined, | ||
>(list: T): list is T & PresentArrayFor<T> { | ||
@@ -25,11 +30,11 @@ return list && list.length > EMPTY_LENGTH; | ||
list: PresentArray<T>, | ||
mapper: (item: T, index: number) => U | ||
mapper: (item: T, index: number) => U, | ||
): MutablePresentArray<U>; | ||
export function mapArray<T, U>( | ||
list: T[] | readonly T[], | ||
mapper: (item: T, index: number) => U | ||
mapper: (item: T, index: number) => U, | ||
): U[]; | ||
export function mapArray<T, U>( | ||
list: T[] | readonly T[] | PresentArray<T>, | ||
mapper: (item: T, index: number) => U | ||
mapper: (item: T, index: number) => U, | ||
): U[] | PresentArray<U> { | ||
@@ -41,3 +46,3 @@ return list.map(mapper); | ||
list: PresentArray<T>, | ||
mapper: (item: T, index: number) => U | ||
mapper: (item: T, index: number) => U, | ||
): PresentArray<U> { | ||
@@ -49,11 +54,11 @@ return list.map(mapper) as PresentArray<U>; | ||
list: T[] | undefined | null, | ||
mapper: (item: T, index: number) => U | ||
mapper: (item: T, index: number) => U, | ||
): MutablePresentArray<U> | undefined; | ||
export function mapIfPresent<T, U>( | ||
list: readonly T[] | undefined | null, | ||
mapper: (item: T, index: number) => U | ||
mapper: (item: T, index: number) => U, | ||
): ReadonlyPresentArray<U> | undefined; | ||
export function mapIfPresent<T, U>( | ||
list: T[] | readonly T[] | undefined | null, | ||
mapper: (item: T, index: number) => U | ||
mapper: (item: T, index: number) => U, | ||
): MutablePresentArray<U> | ReadonlyPresentArray<U> | undefined { | ||
@@ -69,11 +74,11 @@ if (list && isPresentArray(list)) { | ||
T extends [unknown, ...unknown[]] | readonly [unknown, ...unknown[]], | ||
U | ||
U, | ||
>(list: T, callback: (value: PresentArrayFor<T>) => U): U; | ||
export function ifPresentArray<T extends unknown[] | readonly unknown[], U>( | ||
list: T | undefined | null, | ||
callback: (value: PresentArrayFor<T>) => U | ||
callback: (value: PresentArrayFor<T>) => U, | ||
): U | undefined; | ||
export function ifPresentArray<T extends unknown[] | readonly unknown[], U>( | ||
list: T | undefined | null, | ||
callback: (value: PresentArrayFor<T>) => U | ||
callback: (value: PresentArrayFor<T>) => U, | ||
): U | undefined { | ||
@@ -89,10 +94,16 @@ if (list && isPresentArray(list)) { | ||
export function isSingleItemArray<T>( | ||
list: T[] | readonly T[] | undefined | null | ||
): list is [T] { | ||
return list?.length === SINGLE_ITEM; | ||
export function isSingleItemArray<T>(list: T): list is T & [ArrayItem<T>] { | ||
return Array.isArray(list) && list.length === SINGLE_ITEM; | ||
} | ||
export function isEmptyCollection(collection: { size: number }): boolean { | ||
return collection.size === EMPTY_LENGTH; | ||
} | ||
export function isPresentCollection(collection: { size: number }): boolean { | ||
return collection.size > EMPTY_LENGTH; | ||
} | ||
export function isEmptyArray<T extends unknown[] | readonly unknown[]>( | ||
list: T | ||
list: T, | ||
): list is T & [] { | ||
@@ -105,3 +116,3 @@ return list.length === EMPTY_LENGTH; | ||
b: U[] | readonly U[], | ||
zipper: (a: T, b: U) => V | ||
zipper: (a: T, b: U) => V, | ||
): readonly V[] { | ||
@@ -118,3 +129,3 @@ const result: V[] = []; | ||
export function nullifyEmptyArray<U extends unknown[] | readonly unknown[]>( | ||
list: U | ||
list: U, | ||
): PresentArrayFor<U> | null { | ||
@@ -124,8 +135,8 @@ return isEmptyArray(list) ? null : (list as unknown as PresentArrayFor<U>); | ||
const FIRST_OFFSET = 0; | ||
export const FIRST_OFFSET = 0; | ||
const TAIL_OFFSET = 1; | ||
const LAST_OFFSET = -1; | ||
export const LAST_OFFSET = -1; | ||
export function withoutFirst<T, U extends unknown[]>( | ||
list: [T, ...U] | readonly [T, ...U] | ||
list: [T, ...U] | readonly [T, ...U], | ||
): U; | ||
@@ -141,10 +152,14 @@ export function withoutFirst<T>(list: T[] | readonly T[]): T[]; | ||
export function firstNItems<T>(list: T[], n: number): T[] { | ||
export function firstNItems<T>(list: readonly T[], n: number): readonly T[]; | ||
export function firstNItems<T>(list: T[], n: number): T[]; | ||
export function firstNItems<T>( | ||
list: T[] | readonly T[], | ||
n: number, | ||
): T[] | readonly T[] { | ||
return list.slice(FIRST_OFFSET, n); | ||
} | ||
export function getFirst<I>( | ||
list: [I, ...unknown[]] | readonly [I, ...unknown[]] | ||
): I; | ||
export function getFirst<T>(list: PresentArray<T>): T; | ||
export function getFirst<const T extends unknown[] | readonly unknown[]>( | ||
list: T, | ||
): T[0]; | ||
export function getFirst<T>(list: AnyArray<T> | undefined): T | undefined; | ||
@@ -155,6 +170,86 @@ export function getFirst<T>(list: AnyArray<T> | undefined): T | undefined { | ||
// Borrowed from SimplyTyped: | ||
type Prev<T extends number> = [ | ||
-1, | ||
0, | ||
1, | ||
2, | ||
3, | ||
4, | ||
5, | ||
6, | ||
7, | ||
8, | ||
9, | ||
10, | ||
11, | ||
12, | ||
13, | ||
14, | ||
15, | ||
16, | ||
17, | ||
18, | ||
19, | ||
20, | ||
21, | ||
22, | ||
23, | ||
24, | ||
25, | ||
26, | ||
27, | ||
28, | ||
29, | ||
30, | ||
31, | ||
32, | ||
33, | ||
34, | ||
35, | ||
36, | ||
37, | ||
38, | ||
39, | ||
40, | ||
41, | ||
42, | ||
43, | ||
44, | ||
45, | ||
46, | ||
47, | ||
48, | ||
49, | ||
50, | ||
51, | ||
52, | ||
53, | ||
54, | ||
55, | ||
56, | ||
57, | ||
58, | ||
59, | ||
60, | ||
61, | ||
62, | ||
][T]; | ||
// Actual, legit sorcery | ||
// Borrowed from pelotom/hkts: | ||
type GetLength<original extends unknown[] | readonly unknown[]> = | ||
original extends { | ||
length: infer L; | ||
} | ||
? L | ||
: never; | ||
type GetLast<original extends unknown[] | readonly unknown[]> = original[Prev< | ||
GetLength<original> | ||
>]; | ||
export function getLast<T extends AnyArray<unknown>>(list: T): GetLast<T>; | ||
export function getLast<T>(list: PresentArray<T>): T; | ||
export function getLast<T>(list: T[] | readonly T[] | undefined): T | undefined; | ||
export function getLast<T>( | ||
list: readonly T[] | T[] | undefined | ||
list: readonly T[] | T[] | undefined, | ||
): T | undefined { | ||
@@ -166,6 +261,6 @@ return isPresentArray(list) ? list[getLastIndex(list)] : undefined; | ||
export function getLastIndex( | ||
list: unknown[] | readonly unknown[] | ||
list: unknown[] | readonly unknown[], | ||
): number | undefined; | ||
export function getLastIndex( | ||
list: unknown[] | readonly unknown[] | ||
list: unknown[] | readonly unknown[], | ||
): number | undefined { | ||
@@ -192,6 +287,6 @@ if (isPresentArray(list)) { | ||
export function isArray<T>( | ||
export function isArray<T extends AnyArray<unknown>>( | ||
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents | ||
value: unknown | readonly T[] | ||
): value is readonly T[]; | ||
value: unknown | T, | ||
): value is T; | ||
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents | ||
@@ -198,0 +293,0 @@ export function isArray<T>(value: unknown | T[]): value is T[]; |
@@ -11,3 +11,3 @@ import { getFirst, isPresentArray, isSingleItemArray } from "./array.js"; | ||
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never; | ||
export type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never; | ||
@@ -20,7 +20,12 @@ type WithReadonly<T, K extends keyof T> = Expand< | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
/* | ||
eslint-disable @typescript-eslint/no-explicit-any -- These `any`s are necessary | ||
because they express the full generalization of the key, function and | ||
descriptor types. These `any`s avoid unchecked `any`s in other part of this | ||
file. | ||
*/ | ||
type AnyKey = keyof any; | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
type AnyFunction = (...args: any[]) => any; | ||
type AnyTypedDescriptorMap = Record<string, TypedPropertyDescriptor<any>>; | ||
/* eslint-enable @typescript-eslint/no-explicit-any */ | ||
@@ -41,3 +46,3 @@ type DefineReadonly<T, K extends AnyKey, V> = Expand< | ||
export function method<T, K extends AnyKey, V extends AnyFunction>( | ||
fn: V | ||
fn: V, | ||
): Define<T, { [P in K]: V }>; | ||
@@ -55,3 +60,3 @@ export function method(fn: AnyFunction): TypedPropertyDescriptor<AnyFunction> { | ||
key: K, | ||
fn: T[K] & AnyFunction | ||
fn: T[K] & AnyFunction, | ||
): T; | ||
@@ -61,3 +66,3 @@ export function defMethod<T, K extends AnyKey, V extends AnyFunction>( | ||
key: K, | ||
fn: V | ||
fn: V, | ||
): Define<T, { [P in K]: V }>; | ||
@@ -67,3 +72,3 @@ export function defMethod( | ||
key: AnyKey, | ||
fn: AnyFunction | ||
fn: AnyFunction, | ||
): object { | ||
@@ -83,3 +88,3 @@ Object.defineProperty(object, key, { | ||
key: K, | ||
fn: (object: T) => T[K] | ||
fn: (object: T) => T[K], | ||
): T; | ||
@@ -89,3 +94,3 @@ export function getter<T, K extends AnyKey, V>( | ||
key: K, | ||
fn: (object: T) => V | ||
fn: (object: T) => V, | ||
): Define<T, { readonly [P in K]: V }>; | ||
@@ -95,3 +100,3 @@ export function getter( | ||
key: AnyKey, | ||
fn: (object: object) => unknown | ||
fn: (object: object) => unknown, | ||
): object { | ||
@@ -114,6 +119,5 @@ Object.defineProperty(object, key, { | ||
export function defineObject< | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
R extends Record<string, TypedPropertyDescriptor<any>> | ||
>(properties: R): DefinedObject<R> { | ||
export function defineObject<R extends AnyTypedDescriptorMap>( | ||
properties: R, | ||
): DefinedObject<R> { | ||
return Object.defineProperties({}, properties) as DefinedObject<R>; | ||
@@ -129,6 +133,5 @@ } | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
export function def<T, R extends Record<string, TypedPropertyDescriptor<any>>>( | ||
export function def<T, R extends AnyTypedDescriptorMap>( | ||
object: T, | ||
properties: R | ||
properties: R, | ||
): T & DefinedObject<R> { | ||
@@ -146,3 +149,3 @@ return Object.defineProperties(object, properties) as T & DefinedObject<R>; | ||
key: K, | ||
value: V | ||
value: V, | ||
): DefineReadonly<T, K, V>; | ||
@@ -149,0 +152,0 @@ export function readonly( |
{ | ||
"root": false, | ||
"overrides": [ | ||
{ | ||
"extends": ["plugin:@starbeam/loose"], | ||
"files": ["**/*.ts"], | ||
"parserOptions": { | ||
"project": "tsconfig.json" | ||
} | ||
} | ||
] | ||
"root": true, | ||
"extends": ["plugin:@starbeam-dev/library:recommended"] | ||
} |
@@ -1,11 +0,7 @@ | ||
import { isObject } from "@starbeam/core-utils"; | ||
import { describe, expect, test } from "vitest"; | ||
describe("object utils", () => { | ||
test("isObject", () => { | ||
expect(isObject(null)).toBe(false); | ||
expect(isObject({})).toBe(true); | ||
expect(isObject(new (class {})())).toBe(true); | ||
expect(isObject([])).toBe(true); | ||
describe("now", () => { | ||
test("ok", () => { | ||
expect(true).toBe(true); | ||
}); | ||
}); |
{ | ||
"private": true, | ||
"name": "@starbeam-tests/core-utils", | ||
"type": "module", | ||
"version": "1.0.0", | ||
"type": "module", | ||
"starbeam:type": "tests", | ||
"starbeam": { | ||
"source": "tsx", | ||
"type": "tests" | ||
}, | ||
"scripts": { | ||
"test:lint": "eslint ", | ||
"test:lint": "eslint . --max-warnings 0", | ||
"test:types": "tsc -b" | ||
@@ -13,3 +16,6 @@ }, | ||
"@starbeam/core-utils": "workspace:^" | ||
}, | ||
"devDependencies": { | ||
"@starbeam-dev/eslint-plugin": "^1.0.4" | ||
} | ||
} |
@@ -5,9 +5,12 @@ { | ||
"composite": true, | ||
"jsx": "react-jsx", | ||
"jsxImportSource": "react", | ||
"types": ["../../../env.d.ts"], | ||
"declaration": true, | ||
"declarationDir": "../../../../dist/types", | ||
"declarationMap": true, | ||
"outDir": "../../../../dist/packages", | ||
"types": ["../../../env"] | ||
"emitDeclarationOnly": true | ||
}, | ||
"include": ["**/*.ts"], | ||
"exclude": ["dist/**/*"] | ||
} |
@@ -5,9 +5,9 @@ { | ||
"composite": true, | ||
"types": ["../../env.d.ts"], | ||
"declaration": true, | ||
"declarationDir": "../../../dist/types", | ||
"declarationMap": true, | ||
"outDir": "../../../dist/packages", | ||
"types": ["../../env"] | ||
"emitDeclarationOnly": true | ||
}, | ||
"exclude": ["dist/**/*"] | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
0
0
25708
3
22
723