Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 113 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ A lightweight **TypeScript** library for basic data management.

- [Installation](#installation)
- [Api](#api)
- `abstract`
- Abstract
- [`Immutability`](#immutability)
- [`DataCore`](#datacore)
- **Base**
- Base
- [`Data`](#data)
- [`Value`](#value)
- **`WeakData`**
- Map
- [`DataMap`](#datamap)
- [`WeakDataMap`](#weakdatamap)
- WeakData
- [`IndexedWeakData`](#indexedweakdata)
- [`WeakData`](#weakdata)
- [Immutability](#immutability)
Expand Down Expand Up @@ -59,6 +62,10 @@ import {
Data,
Value,

// `Map`.
DataMap,
WeakDataMap,

// `WeakData`.
NamedWeakData,
// Indexed.
Expand Down Expand Up @@ -108,6 +115,109 @@ The class to manage the value of generic type variable `Type`.
import { Value } from '@typescript-package/data';
```

### `DataMap`

The `DataMap` is a concrete class that extends `Map` and encapsulates its data within a `DataCore` store, providing additional data management capabilities.

```typescript
import { DataMap } from '@typescript-package/data';

// Define a `DataCore` implementation for holding a data in `DataMap`.
export class CustomMapData<Key, Value> extends Data<Map<Key, Value>> {
constructor(initialValue?: Map<Key, Value>) {
super(initialValue ?? new Map());
}
}

// Create a new `DataMap` instance with predefined entries and customized data holder.
export const dataMap = new DataMap<string, number, CustomMapData<string, number>>(
[
["one", 1],
["two", 2],
["three", 3],
],
new CustomMapData()
);

// Check the `CustomMapData`.
console.log(`Data holder of \`CustomMapData\`:`, dataMap.data); // Output: CustomMapData {#locked: false, #value: Value}

// Get the `CustomMapData` value.
console.log(`Data holder of \`CustomMapData\` value:`, dataMap.data.value); // Output: Map(3) {'one' => 1, 'two' => 2, 'three' => 3}

// Log the size of the map
console.log("Size:", dataMap.size); // Output: Size: 3

// Get a value from the map
console.log("Value for 'two':", dataMap.get("two")); // Output: Value for 'two': 2

// Check if a key exists
console.log("Has 'three'?", dataMap.has("three")); // Output: Has 'three'? true

// Set a new key-value pair
dataMap.set("four", 4);
console.log("Size after set:", dataMap.size); // Output: Size after set: 4

// Iterate over entries
dataMap.forEach((value, key) => console.log(`${key}: ${value}`));
// Output:
// one: 1
// two: 2
// three: 3
// four: 4

// Delete an entry
dataMap.delete("one");
console.log("Size after delete:", dataMap.size); // Output: Size after delete: 3

// Clear the map
dataMap.clear();
console.log("Size after clear:", dataMap.size); // Output: Size after clear: 0

```

### `WeakDataMap`

The `WeakDataMap` class is a concrete class that stores data in a static `WeakMap`.

```typescript
import { WeakDataMap } from '@typescript-package/data';

// Create an instance of `WeakDataMap`.
const weakDataMap = new WeakDataMap<string, number>([
['one', 1],
['two', 2],
['three', 3],
]);


// Get the value from `WeakData` static.
console.log(`data: `, WeakData.get(weakDataMap.data)); // Output: Map(3) {'one' => 1, 'two' => 2, 'three' => 3}

// Get a value by key
console.log(weakDataMap.get('two')); // Output: 2

// Add a new key-value pair
weakDataMap.set('four', 4);

// Check if a key exists
console.log(weakDataMap.has('four')); // Output: true

// Delete a key
weakDataMap.delete('one');

// Iterate over entries
for (const [key, value] of weakDataMap.entries()) {
console.log(key, value);
}

// Output:
// two 2
// three 3
// four 4

```

### `Immutability`

Manages the immutability states of `this` current instance.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typescript-package/data",
"version": "2.0.0",
"version": "2.1.0",
"author": "wwwdev.io <dev@wwwdev.io>",
"description": "A lightweight TypeScript library for basic data management.",
"license": "MIT",
Expand Down
191 changes: 191 additions & 0 deletions src/map/data-map.class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
// Class.
import { Data } from '../lib/data.class';
// Abstract.
import { DataCore } from '../lib/data-core.abstract';
/**
* @description The `DataMap` is a concrete class that extends `Map` and encapsulates its data within a `DataCore` store, providing additional data management capabilities.
* @export
* @class DataMap
* @template Key
* @template Value
* @template {DataCore<Map<Key, Value>>} [DataType=Data<Map<Key, Value>>]
* @extends {Map<Key, Value>}
*/
export class DataMap<
Key,
Value,
DataType extends DataCore<Map<Key, Value>> = Data<Map<Key, Value>>
> {
/**
* @description Returns the `string` tag representation of the `DataMap` class when used in `Object.prototype.toString.call(instance)`.
* @public
* @readonly
*/
public get [Symbol.toStringTag](): string {
return DataMap.name;
}

/**
* @description Returns the privately stored data class.
* @public
* @readonly
* @type {DataType}
*/
public get data() {
return this.#data;
}

/**
* @inheritdoc
* @public
* @readonly
* @type {number}
*/
public get size() {
return this.#data.value.size;
}

/**
* @description A privately stored data holder of generic type variable `DataType` for the `Map`.
* @type {DataType}
*/
#data: DataType;

/**
* Creates an instance of `DataMap`.
* @constructor
* @param {?[Key, Value][]} [entries] Initial value for `Map`.
* @param {?DataType} [data] The data store of generic type variable `DataType` for `Map` value.
*/
constructor(
entries?: [Key, Value][],
data?: DataType
) {
if (data) {
this.#data = data;
(Array.isArray(entries) && this.#data.value.size === 0) && entries.forEach(([key, value]) => this.#data.value.set(key, value));
} else {
this.#data = new Data(new Map(entries)) as unknown as DataType;
}
}

/**
* Clears all entries.
* @inheritdoc
* @public
* @returns {this}
*/
public clear(): this {
this.onClear?.(this.#data);
this.#data.value.clear();
return this;
}

/**
* Deletes a value from the `key`.
* @inheritdoc
* @public
* @param {Key} key The key to delete.
* @returns {boolean}
*/
public delete(key: Key): boolean {
return this.#data.value.delete(key);
}

/**
* @inheritdoc
*/
public entries(): IterableIterator<[Key, Value]> {
return this.#data.value.entries();
}

/**
* @inheritdoc
* @public
* @param {(value: Value, key: Key, map: Map<Key, Value>) => void} callbackfn
* @param {?*} [thisArg]
* @returns {this}
*/
public forEach(callbackfn: (value: Value, key: Key, map: Map<Key, Value>) => void, thisArg?: any): this {
this.#data.value.forEach(callbackfn, thisArg);
return this;
}

/**
* @inheritdoc
* @public
* @param {Key} key The key to get the value.
*/
public get(key: Key): Value | undefined {
return this.onGet?.(key, this.#data), this.#data.value.get(key);
}

/**
* @inheritdoc
* @public
* @param {Key} key The key to check.
* @returns {boolean}
*/
public has(key: Key): boolean {
return this.onGet?.(key, this.#data), this.#data.value.has(key);
}

/**
* @inheritdoc
*/
public keys(): MapIterator<Key> {
return this.#data.value.keys();
}

/**
* @inheritdoc
* @public
* @param {Key} key The key under which the `value` set.
* @param {Value} value The value of `Value` type.
* @returns {this} The `this` current instance for chaining.
*/
public set(key: Key, value: Value): this {
this.onSet?.(key, value, this.get(key)!, this.#data);
this.#data.value.set(key, value);
return this;
}

/**
* @inheritdoc
*/
public values(): MapIterator<Value> {
return this.#data.value.values();
}

/**
* @description Hook called when the `Map` is cleared.
* @protected
* @param {DataType} data The data holder.
*/
protected onClear(data: DataType): void {}

/**
* @description Hook called when a value is deleted.
* @protected
* @param {DataType} data The data holder.
*/
protected onDelete(key: Key, data: DataType): void {}

/**
* @description Hook called before the `get` being invoked.
* @protected
* @param {Key} key The key to get the value.
* @param {DataType} data The data holder.
*/
protected onGet(key: Key, data: DataType): void {}

/**
* @description Hook called when a value is added.
* @protected
* @param {key} key The key under which set the `value`.
* @param {Type} value The value to set.
* @param {Type} previousValue The previous value.
* @param {DataType} data The data holder.
*/
protected onSet(key: Key, value: Value, previousValue: Value, data: DataType): void {}
}
2 changes: 2 additions & 0 deletions src/map/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { DataMap } from './data-map.class';
export { WeakDataMap } from './weak-data-map.class';
31 changes: 31 additions & 0 deletions src/map/weak-data-map.class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Class.
import { DataMap } from './data-map.class';
import { WeakData } from '../lib';
/**
* @description The `WeakDataMap` class is a concrete class that stores data in a static `WeakMap`.
* @export
* @class WeakDataMap
* @template Key
* @template Value
* @extends {DataMap<Key, Value, WeakData<Map<Key, Value>>>}
*/
export class WeakDataMap<Key, Value> extends DataMap<Key, Value, WeakData<Map<Key, Value>>> {
/**
* @description Returns the `string` tag representation of the `WeakDataMap` class when used in `Object.prototype.toString.call(instance)`.
* @public
* @readonly
* @type {string}
*/
public override get [Symbol.toStringTag](): string {
return WeakDataMap.name;
}

/**
* Creates an instance of `WeakDataMap`.
* @constructor
* @param {?[Key, Value][]} [entries]
*/
constructor(entries?: [Key, Value][]) {
super(entries, new WeakData(new Map(entries)));
}
}
5 changes: 5 additions & 0 deletions src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ export {
// Basic.
WeakData,
} from './lib';
// Map related.
export {
DataMap,
WeakDataMap,
} from './map';
Loading