Skip to content

Commit

Permalink
Merge branch 'dev'; tag v0.25.0
Browse files Browse the repository at this point in the history
  • Loading branch information
chharvey committed Jul 10, 2022
2 parents a6736db + dd926dd commit 1f83ae5
Show file tree
Hide file tree
Showing 28 changed files with 850 additions and 586 deletions.
604 changes: 228 additions & 376 deletions package-lock.json

Large diffs are not rendered by default.

15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "extrajs",
"version": "0.24.1",
"version": "0.25.0",
"description": "Javascript helpers for lazy people.",
"keywords": [
"javascript",
Expand All @@ -20,26 +20,27 @@
"tsconfig.json"
],
"main": "dist/index.js",
"type": "module",
"repository": {
"type": "git",
"url": "git+https://github.com/chharvey/extrajs.git"
},
"scripts": {
"dist": "tsc",
"test": "mocha -r ts-node/register ./test/*.ts",
"test": "mocha -r ts-node/esm --loader='ts-node/esm' './test/*.ts'",
"docs": "typedoc",
"build": "rm -rf ./dist/ ./docs/api/ && npm run dist && npm run test && npm run docs",
"prepublishOnly": "npm run build"
},
"devDependencies": {
"@types/mocha": "^9.0.0",
"@types/node": "^17.0.0",
"mocha": "^9.0.0",
"@types/node": "^18.0.0",
"mocha": "^10.0.0",
"ts-node": "^10.0.0",
"typedoc": "^0.21.0",
"typescript": "~4.3.0"
"typedoc": "^0.23.0",
"typescript": "~4.7.0"
},
"engines": {
"node": ">=14"
"node": ">=16"
}
}
61 changes: 0 additions & 61 deletions src/MapEq.ts

This file was deleted.

122 changes: 113 additions & 9 deletions src/class/Array.class.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import xjs_Object from './Object.class'
import xjs_Number from './Number.class'
import IndexOutOfBoundsError from './IndexOutOfBoundsError.class'
import {xjs_Object} from './Object.class.js';
import {xjs_Number} from './Number.class.js';
import {IndexOutOfBoundsError} from './IndexOutOfBoundsError.class.js';


/**
* Additional static members for the native Array class.
*
* Does not extend the native Array class.
*/
export default class xjs_Array {
export class xjs_Array {
/**
* Get a value of an array, given an index.
*
Expand All @@ -26,11 +26,10 @@ export default class xjs_Array {
}

/**
* @deprecated - WARNING{DEPRECATED} - use {@link xjs_Array.isConsecutiveSuperarrayOf} instead.
* Test whether an array is a subarray of another array.
*
* This method acts like
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes|String#includes},
* {@link String#includes},
* testing whether
* the elements in the smaller array appear consecutively and in the same order as in the larger array.
* In other words, if `{@link xjs_Array.is}(larger.slice(a,b), smaller)` (for some integers a and b),
Expand All @@ -55,6 +54,7 @@ export default class xjs_Array {
* @param predicate check the “sameness” of corresponding elements of `larger` and `smaller`
* @returns is `smaller` a subarray of `larger`?
* @throws {RangeError} if the second array is larger than the first
* @deprecated use {@link xjs_Array.isConsecutiveSuperarrayOf} instead.
*/
static contains<T>(larger: readonly T[], smaller: readonly T[], predicate: (x: T, y: T) => boolean = xjs_Object.sameValueZero): boolean {
if (smaller.length > larger.length) {
Expand Down Expand Up @@ -192,15 +192,119 @@ export default class xjs_Array {
return (await xjs_Array.filterAsync(arr, predicate, this_arg))[0] || null
}

/**
* Perform a callback function on an array, aggregating any errors caught.
*
* Instead of throwing on the first error and stopping iteration, as {@link Array#forEach} would do,
* this method continues performing the callback on the rest of the array until all items are done.
* If only one error was caught, then that error is simply rethrown.
* However, if more errors were caught, they are collected into a single AggregateError, which is then thrown.
* If no errors are caught, this method returns void.
*
* @example
* xjs.Array.forEachAggregated<number>([1, 2, 3, 4], (n) => {
* if (n % 2 === 0) {
* throw new Error(`${ n } is even.`);
* };
* });
* // Expected thrown error:
* AggregateError {
* errors: [
* Error { message: "2 is even." },
* Error { message: "4 is even." },
* ]
* }
* @typeparam T the type of items in the array
* @param array the array of items
* @param callback the function to call on each item
* @throws {AggregateError} if two or more iterations throws an error
* @throws {Error} if one iteration throws an error
*/
static forEachAggregated<T>(array: readonly T[], callback: (item: T, i: number, src: readonly T[]) => void): void {
const errors: readonly Error[] = array.map((it, i, src) => {
try {
callback.call(null, it, i, src);
return null;
} catch (err) {
return (err instanceof Error) ? err : new Error(`${ err }`);
}
}).filter((e): e is Error => e instanceof Error);
if (errors.length) {
throw (errors.length === 1)
? errors[0]
: new AggregateError(errors, errors.map((err) => err.message).join('\n'));
}
}

/**
* Map an array using a callback, aggregating any errors caught.
*
* Instead of throwing on the first error and stopping iteration, as {@link Array#map} would do,
* this method continues performing the callback on the rest of the array until all items are done.
* If only one error was caught, then that error is simply rethrown.
* However, if more errors were caught, they are collected into a single AggregateError, which is then thrown.
* If no errors are caught, this method returns the usual map.
*
* @example
* xjs.Array.mapAggregated<number>([1, 2, 3, 4], (n) => {
* if (n % 2 === 1) {
* throw new Error(`${ n } is odd.`);
* } else {
* return n / 2;
* };
* });
* // Expected thrown error:
* AggregateError {
* errors: [
* Error { message: "1 is odd." },
* Error { message: "3 is odd." },
* ]
* }
*
* xjs.Array.mapAggregated<number>([2, 4, 6], (n) => {
* if (n % 2 === 1) {
* throw new Error(`${ n } is odd.`);
* } else {
* return n / 2;
* };
* });
* // Expected return value:
* [1, 2, 3]
* @typeparam T the type of items in the array
* @typeparam U the type of items returned by the mapping callback
* @param array the array of items
* @param callback the function to call on each item
* @returns the array of mapped items
* @throws {AggregateError} if two or more iterations throws an error
* @throws {Error} if one iteration throws an error
*/
static mapAggregated<T, U>(array: readonly T[], callback: (item: T, i: number, src: readonly T[]) => U): U[] {
const results: ([U, true] | [Error, false])[] = array.map((it, i, src) => {
try {
return [callback(it, i, src), true];
} catch (err) {
return [(err instanceof Error) ? err : new Error(`${ err }`), false];
}
});
const errors: Error[] = results.filter((pair): pair is [Error, false] => !pair[1]).map(([err]) => err);
if (errors.length) {
throw (errors.length === 1)
? errors[0]
: new AggregateError(errors, errors.map((err) => err.message).join('\n'));
} else {
return results.filter((pair): pair is [U, true] => pair[1]).map(([val]) => val);
}
}

/**
* @deprecated WARNING{DEPRECATED} - use interface `readonly T[]` instead
* Deep freeze an array, and return the result.
*
* Shortcut of {@link xjs_Object.freezeDeep}, but for arrays.
* Warning: passing in a sparse array can yield unexpected results.
* *Note: This function is impure, modifying the given argument.*
* @param arr the array to freeze
* @returns the given array, with everything frozen
* @deprecated use interface `readonly T[]` instead
*/
static freezeDeep<T>(arr: readonly T[]): readonly T[] {
Object.freeze(arr)
Expand All @@ -209,7 +313,7 @@ export default class xjs_Array {
}

/**
* WARNING{EXPERIMENTAL}
* WARNING:EXPERIMENTAL
* Deep clone an array, and return the result.
*
* Shortcut of {@link xjs_Object.cloneDeep}, but for arrays.
Expand All @@ -223,7 +327,6 @@ export default class xjs_Array {
}

/**
* @deprecated WARNING{DEPRECATED} - use `[...new Set(arr)]` instead
* Make a copy of an array, and then remove duplicate entries.
*
* "Duplicate entries" are entries that considered "the same" by
Expand All @@ -234,6 +337,7 @@ export default class xjs_Array {
* @param arr an array to use
* @param predicate check the “sameness” of elements in the array
* @returns a new array, with duplicates removed
* @deprecated use `[...new Set(arr)]` instead
*/
static removeDuplicates<T>(arr: readonly T[], predicate: (x: T, y: T) => boolean = xjs_Object.sameValueZero): T[] {
const returned: T[] = arr.slice()
Expand Down
4 changes: 2 additions & 2 deletions src/class/BigInt.class.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import * as assert from 'assert'

import {NumericType} from './Number.class'
import {NumericType} from './Number.class.js';


/**
* Additional static members for the native BigInt class.
*
* Does not extend the native BigInt class.
*/
export default class xjs_BigInt {
export class xjs_BigInt {
/**
* Verify the type of bigint given, throwing if it does not match.
*
Expand Down
2 changes: 1 addition & 1 deletion src/class/Date.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Does not extend the native Date class.
*/
export default class xjs_Date {
export class xjs_Date {
/**
* The list of full month names in English.
*/
Expand Down
4 changes: 2 additions & 2 deletions src/class/IndexOutOfBoundsError.class.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import xjs_Number from './Number.class'
import {xjs_Number} from './Number.class.js';

/**
* An error that is thrown when trying to access an object’s member
* with an index that has not been set or is outside the domain of the object.
*/
export default class IndexOutOfBoundsError extends RangeError {
export class IndexOutOfBoundsError extends RangeError {
/**
* Construct a new IndexOutOfBoundsError object.
* @param message Optional. A human-readable description of the error.
Expand Down
Loading

0 comments on commit 1f83ae5

Please sign in to comment.