@geraintguan/ts-std-lib 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @geraintguan/ts-std-lib
1
+ # Typescript Standard Library
2
2
 
3
3
  [![Coverage
4
4
  Status](https://coveralls.io/repos/github/geraintguan/ts-std-lib/badge.svg?branch=main)](https://coveralls.io/github/geraintguan/ts-std-lib?branch=main)
@@ -6,7 +6,7 @@ Status](https://coveralls.io/repos/github/geraintguan/ts-std-lib/badge.svg?branc
6
6
 
7
7
  [API Reference](https://ts-std-lib.geraint.io)
8
8
 
9
- A practical and pragmatic standard library for TypeScript (and JavaScript).
9
+ A practical and pragmatic universal standard library for TypeScript targeting Browser/Node.js runtimes.
10
10
 
11
11
  ## Installation
12
12
 
@@ -1,25 +1,22 @@
1
- var __defProp = Object.defineProperty;
2
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
1
  import { identity } from "../identity.mjs";
5
2
  import { HashMap } from "./HashMap.mjs";
6
3
  class DefaultMap extends HashMap {
4
+ /**
5
+ * Default value to use in this map when accessing keys that do not exist.
6
+ *
7
+ * @remarks
8
+ *
9
+ * Two types of default value are supported:
10
+ *
11
+ * 1. Providing a **function** will make the map call the given function that
12
+ * is called with the current access key to generate the default value.
13
+ *
14
+ * 2. Providing a static **value** that will be used as-is as the default
15
+ * value.
16
+ */
17
+ defaultValue;
7
18
  constructor(defaultValue, hash, map = /* @__PURE__ */ new Map(), name = "unknown") {
8
19
  super(hash, map, name);
9
- /**
10
- * Default value to use in this map when accessing keys that do not exist.
11
- *
12
- * @remarks
13
- *
14
- * Two types of default value are supported:
15
- *
16
- * 1. Providing a **function** will make the map call the given function that
17
- * is called with the current access key to generate the default value.
18
- *
19
- * 2. Providing a static **value** that will be used as-is as the default
20
- * value.
21
- */
22
- __publicField(this, "defaultValue");
23
20
  this.defaultValue = defaultValue;
24
21
  }
25
22
  /**
@@ -1,8 +1,20 @@
1
- declare class HashMapMissingKeyError<TKey, TValue, TSerializedKey> extends Error {
2
- readonly key: TKey;
3
- readonly map: HashMap<TKey, TValue, TSerializedKey>;
4
- constructor(map: HashMap<TKey, TValue, TSerializedKey>, key: TKey);
5
- }
1
+ /**
2
+ * Function called to filter the entries in a map.
3
+ *
4
+ * @remarks
5
+ *
6
+ * It is possible to mutate the original map as you filter the entries in the
7
+ * map though this is not recommended in most cases as it is easy to introduce
8
+ * bugs in your code this way.
9
+ *
10
+ * @param value - The value of the entry in the map being filtered.
11
+ * @param key - The key of the entry in the map being filtered.
12
+ * @param index - The index of the entry in the map being filtered.
13
+ * @param original - The original map instance being filtered.
14
+ *
15
+ * @returns `true` to include the entry in the new map or `false` to exclude it.
16
+ */
17
+ export type HashMapFilterFn<TKey, TValue, THashedKey> = (value: TValue, key: THashedKey, index: number, original: HashMap<TKey, TValue, THashedKey>) => boolean;
6
18
  /**
7
19
  * Options for creating a new map instance.
8
20
  */
@@ -22,23 +34,11 @@ export interface HashMapOptions<TKey, THashedKey = TKey> {
22
34
  */
23
35
  name?: string;
24
36
  }
25
- /**
26
- * Function called to filter the entries in a map.
27
- *
28
- * @remarks
29
- *
30
- * It is possible to mutate the original map as you filter the entries in the
31
- * map though this is not recommended in most cases as it is easy to introduce
32
- * bugs in your code this way.
33
- *
34
- * @param value - The value of the entry in the map being filtered.
35
- * @param key - The key of the entry in the map being filtered.
36
- * @param index - The index of the entry in the map being filtered.
37
- * @param original - The original map instance being filtered.
38
- *
39
- * @returns `true` to include the entry in the new map or `false` to exclude it.
40
- */
41
- export type HashMapFilterFn<TKey, TValue, THashedKey> = (value: TValue, key: THashedKey, index: number, original: HashMap<TKey, TValue, THashedKey>) => boolean;
37
+ declare class HashMapMissingKeyError<TKey, TValue, TSerializedKey> extends Error {
38
+ readonly key: TKey;
39
+ readonly map: HashMap<TKey, TValue, TSerializedKey>;
40
+ constructor(map: HashMap<TKey, TValue, TSerializedKey>, key: TKey);
41
+ }
42
42
  /**
43
43
  * Implementation of a key-value map that allows you to customise the way keys
44
44
  * are stored by using a custom hashing function.
@@ -1,24 +1,26 @@
1
- var __defProp = Object.defineProperty;
2
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
1
  import { identity } from "../identity.mjs";
5
2
  class HashMapMissingKeyError extends Error {
3
+ key;
4
+ map;
6
5
  constructor(map, key) {
7
6
  super(
8
7
  `Could not find key ${String(key)} (${typeof key}) in HashMap ${map.name}`
9
8
  );
10
- __publicField(this, "key");
11
- __publicField(this, "map");
12
9
  this.map = map;
13
10
  this.key = key;
14
11
  }
15
12
  }
16
- const _HashMap = class _HashMap {
13
+ class HashMap {
17
14
  constructor(hash, _map = /* @__PURE__ */ new Map(), name = "unknown") {
18
15
  this.hash = hash;
19
16
  this._map = _map;
20
17
  this.name = name;
21
18
  }
19
+ /**
20
+ * Error thrown when attempting to access a key in the map that
21
+ * does not exist.
22
+ */
23
+ static MissingKeyError = HashMapMissingKeyError;
22
24
  /**
23
25
  * Create a new empty map instance.
24
26
  *
@@ -45,7 +47,7 @@ const _HashMap = class _HashMap {
45
47
  * @returns A new empty map instance.
46
48
  */
47
49
  static empty(options = {}) {
48
- return new _HashMap(identity, /* @__PURE__ */ new Map(), options.name);
50
+ return new HashMap(identity, /* @__PURE__ */ new Map(), options.name);
49
51
  }
50
52
  /**
51
53
  * Create a new empty map instance with a custom hashing function.
@@ -55,7 +57,7 @@ const _HashMap = class _HashMap {
55
57
  * @returns A new empty map instance.
56
58
  */
57
59
  static emptyWithCustomHash(options) {
58
- return new _HashMap(
60
+ return new HashMap(
59
61
  options.hash,
60
62
  /* @__PURE__ */ new Map(),
61
63
  options.name
@@ -95,7 +97,7 @@ const _HashMap = class _HashMap {
95
97
  * a given custom hashing function.
96
98
  */
97
99
  static fromCustomEntries(entries, options) {
98
- return new _HashMap(
100
+ return new HashMap(
99
101
  options.hash,
100
102
  new Map(entries.map(([k, v]) => [options.hash(k), v])),
101
103
  options.name
@@ -134,7 +136,7 @@ const _HashMap = class _HashMap {
134
136
  * @returns A new map instance with the given key-value pairs.
135
137
  */
136
138
  static fromEntries(entries, options = {}) {
137
- return new _HashMap(
139
+ return new HashMap(
138
140
  identity,
139
141
  new Map(entries.map(([key, value]) => [key, value])),
140
142
  options.name
@@ -193,7 +195,7 @@ const _HashMap = class _HashMap {
193
195
  */
194
196
  delete(key) {
195
197
  if (!this.has(key)) {
196
- throw new _HashMap.MissingKeyError(this, key);
198
+ throw new HashMap.MissingKeyError(this, key);
197
199
  }
198
200
  this._map.delete(this.hash(key));
199
201
  }
@@ -319,7 +321,7 @@ const _HashMap = class _HashMap {
319
321
  entries.push([key, value]);
320
322
  }
321
323
  }
322
- return new _HashMap(this.hash, new Map(entries), this.name);
324
+ return new HashMap(this.hash, new Map(entries), this.name);
323
325
  }
324
326
  /**
325
327
  * Get the value with the given key from this map, throwing a
@@ -416,7 +418,7 @@ const _HashMap = class _HashMap {
416
418
  for (const [key, value] of this.entries()) {
417
419
  entries.push(fn(value, key, entries.length, this));
418
420
  }
419
- return new _HashMap(this.hash, new Map(entries), this.name);
421
+ return new HashMap(this.hash, new Map(entries), this.name);
420
422
  }
421
423
  /**
422
424
  * Create a new map with entries that have keys that are the result of calling
@@ -491,13 +493,7 @@ const _HashMap = class _HashMap {
491
493
  values() {
492
494
  return this._map.values();
493
495
  }
494
- };
495
- /**
496
- * Error thrown when attempting to access a key in the map that
497
- * does not exist.
498
- */
499
- __publicField(_HashMap, "MissingKeyError", HashMapMissingKeyError);
500
- let HashMap = _HashMap;
496
+ }
501
497
  export {
502
498
  HashMap
503
499
  };
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Groups elements of an array by a key derived from each element, keeping only
3
+ * the last occurrence of each key.
4
+ *
5
+ * @remarks
6
+ * This function is useful when you want to group elements by a key but you know
7
+ * that each element can only appear once per key, or when you only care about
8
+ * the most recent value for each key.
9
+ *
10
+ * Unlike a traditional `groupBy()` function which returns an array of values
11
+ * for each key, this function returns a single value per key. If multiple
12
+ * elements produce the same key, only the latest (last) element in the array
13
+ * will be retained.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const users = [
18
+ * { id: 1, name: "Alice" },
19
+ * { id: 2, name: "Bob" },
20
+ * { id: 3, name: "Charlie" },
21
+ * ];
22
+ *
23
+ * groupByUnique(users, (user) => user.id);
24
+ * // => {
25
+ * // 1: { id: 1, name: "Alice" },
26
+ * // 2: { id: 2, name: "Bob" },
27
+ * // 3: { id: 3, name: "Charlie" },
28
+ * // }
29
+ * ```
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * // When there are duplicate keys, the last value wins
34
+ * const items = [
35
+ * { key: "a", value: 1 },
36
+ * { key: "b", value: 2 },
37
+ * { key: "a", value: 3 },
38
+ * ];
39
+ *
40
+ * groupByUnique(items, (item) => item.key);
41
+ * // => {
42
+ * // a: { key: "a", value: 3 },
43
+ * // b: { key: "b", value: 2 },
44
+ * // }
45
+ * ```
46
+ *
47
+ * @param array - The array of elements to group.
48
+ * @param keyFn - A function that takes each element and returns the key to
49
+ * group by.
50
+ *
51
+ * @returns An object where each key is derived from the key function and each
52
+ * value is the corresponding (last) element from the array.
53
+ */
54
+ export declare function groupByUnique<T, K extends PropertyKey>(array: T[], keyFn: (value: T) => K): Record<K, T>;
@@ -0,0 +1,11 @@
1
+ function groupByUnique(array, keyFn) {
2
+ const result = {};
3
+ for (const item of array) {
4
+ const key = keyFn(item);
5
+ result[key] = item;
6
+ }
7
+ return result;
8
+ }
9
+ export {
10
+ groupByUnique
11
+ };
package/package.json CHANGED
@@ -1,14 +1,17 @@
1
1
  {
2
2
  "name": "@geraintguan/ts-std-lib",
3
- "version": "1.0.0",
3
+ "description": "A practical and pragmatic universal standard library for TypeScript targeting Browser/Node.js runtimes.",
4
+ "version": "1.2.0",
4
5
  "license": "MIT",
6
+ "repository": {
7
+ "url": "https://github.com/geraintguan/ts-std-lib"
8
+ },
5
9
  "type": "module",
6
- "module": "./dist/index.mjs",
7
10
  "exports": {
8
11
  ".": {
9
12
  "import": {
10
- "types": "./dist/index.d.ts",
11
- "default": "./dist/index.mjs"
13
+ "types": "./dist/*.d.ts",
14
+ "default": "./dist/*.mjs"
12
15
  }
13
16
  }
14
17
  },
@@ -19,39 +22,36 @@
19
22
  "fix": "eslint --fix",
20
23
  "lint": "eslint",
21
24
  "test": "vitest",
22
- "typecheck": "pnpm run typecheck:lib && pnpm run typecheck:node",
23
- "typecheck:lib": "tsc --project tsconfig.lib.json --noEmit",
24
- "typecheck:node": "tsc --project tsconfig.node.json --noEmit",
25
+ "typecheck": "tsc --noEmit",
25
26
  "prepare": "husky"
26
27
  },
27
28
  "publishConfig": {
28
29
  "access": "public"
29
30
  },
30
31
  "volta": {
31
- "node": "22.11.0"
32
+ "node": "24.12.0"
32
33
  },
33
34
  "peerDependencies": {
34
35
  "@types/node": ">=20"
35
36
  },
36
37
  "devDependencies": {
37
- "@commitlint/cli": "19.5.0",
38
- "@commitlint/config-conventional": "19.5.0",
39
- "@eslint/js": "9.15.0",
40
- "@tsconfig/node20": "20.1.4",
41
- "@types/eslint__js": "8.42.3",
42
- "@types/node": "22.9.0",
43
- "@vitest/coverage-v8": "2.1.5",
44
- "eslint": "9.15.0",
45
- "eslint-config-prettier": "9.1.0",
46
- "eslint-plugin-perfectionist": "3.9.1",
47
- "eslint-plugin-prettier": "5.2.1",
48
- "husky": "9.1.6",
49
- "semantic-release": "24.2.0",
50
- "typedoc": "0.26.11",
51
- "typescript": "5.6.3",
52
- "typescript-eslint": "8.14.1-alpha.8",
53
- "vite": "5.4.11",
54
- "vite-plugin-dts": "4.3.0",
55
- "vitest": "2.1.5"
38
+ "@commitlint/cli": "19.8.1",
39
+ "@commitlint/config-conventional": "19.8.1",
40
+ "@eslint/js": "9.31.0",
41
+ "@tsconfig/node20": "20.1.6",
42
+ "@types/node": "24.0.14",
43
+ "@vitest/coverage-v8": "3.2.4",
44
+ "eslint": "9.31.0",
45
+ "eslint-config-prettier": "10.1.5",
46
+ "eslint-plugin-perfectionist": "4.15.0",
47
+ "eslint-plugin-prettier": "5.5.1",
48
+ "husky": "9.1.7",
49
+ "semantic-release": "24.2.7",
50
+ "typedoc": "0.28.15",
51
+ "typescript": "5.8.3",
52
+ "typescript-eslint": "8.37.0",
53
+ "vite": "7.0.4",
54
+ "vite-plugin-dts": "4.5.4",
55
+ "vitest": "3.2.4"
56
56
  }
57
57
  }
@@ -1,7 +0,0 @@
1
- /**
2
- * Provides implementations of various useful data structures.
3
- *
4
- * @module Data
5
- */
6
- export * from './DefaultMap.js';
7
- export * from './HashMap.js';
@@ -1,6 +0,0 @@
1
- import { DefaultMap } from "./DefaultMap.mjs";
2
- import { HashMap } from "./HashMap.mjs";
3
- export {
4
- DefaultMap,
5
- HashMap
6
- };
@@ -1 +0,0 @@
1
- export * from './Unpack.js';
package/dist/index.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export * from './constant.js';
2
- export * as Data from './Data/index.js';
3
- export * from './identity.js';
4
- export * as Types from './Types/index.js';
package/dist/index.mjs DELETED
@@ -1,10 +0,0 @@
1
- import { constant } from "./constant.mjs";
2
- import * as index from "./Data/index.mjs";
3
- import { identity } from "./identity.mjs";
4
- import * as index$1 from "./Types/index.mjs";
5
- export {
6
- index as Data,
7
- index$1 as Types,
8
- constant,
9
- identity
10
- };
File without changes