@thi.ng/idgen
Advanced tools
Comparing version 2.1.34 to 2.2.0
# Change Log | ||
- **Last updated**: 2023-06-14T07:58:51Z | ||
- **Last updated**: 2023-08-04T10:58:19Z | ||
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub) | ||
@@ -12,2 +12,14 @@ | ||
## [2.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/idgen@2.2.0) (2023-08-04) | ||
#### 🚀 Features | ||
- update IDGen, add MonotonicID, PrefixedID ([3a73cf0](https://github.com/thi-ng/umbrella/commit/3a73cf0)) | ||
- restructure package | ||
- add/update new impls | ||
#### ♻️ Refactoring | ||
- update INotify impl ([63af221](https://github.com/thi-ng/umbrella/commit/63af221)) | ||
### [2.1.19](https://github.com/thi-ng/umbrella/tree/@thi.ng/idgen@2.1.19) (2022-11-28) | ||
@@ -14,0 +26,0 @@ |
@@ -1,92 +0,5 @@ | ||
import type { Event, IClear, INotify, Listener } from "@thi.ng/api"; | ||
export declare const EVENT_ADDED = "added"; | ||
export declare const EVENT_REMOVED = "removed"; | ||
export declare class IDGen implements Iterable<number>, IClear, INotify { | ||
readonly ids: number[]; | ||
protected nextID: number; | ||
protected _freeID: number; | ||
protected start: number; | ||
protected num: number; | ||
protected _capacity: number; | ||
protected mask: number; | ||
protected vmask: number; | ||
protected shift: number; | ||
constructor(bits?: number, vbits?: number, cap?: number, start?: number); | ||
/** | ||
* Extract actual ID (without version bits). | ||
* | ||
* @param id - | ||
*/ | ||
id(id: number): number; | ||
/** | ||
* Extract version from ID | ||
* | ||
* @param id - | ||
*/ | ||
version(id: number): number; | ||
get capacity(): number; | ||
/** | ||
* Attempts to set new capacity to given value. Capacity can only be | ||
* increased and the operation is only supported for unversioned | ||
* instances (i.e. vbits = 0). | ||
*/ | ||
set capacity(newCap: number); | ||
/** | ||
* Number of remaining available IDs. | ||
*/ | ||
get available(): number; | ||
/** | ||
* Number of currently used IDs. | ||
*/ | ||
get used(): number; | ||
/** | ||
* Next available free ID. | ||
*/ | ||
get freeID(): number; | ||
[Symbol.iterator](): Generator<number, void, unknown>; | ||
/** | ||
* Frees all existing IDs and resets counter to original start ID. | ||
*/ | ||
clear(): void; | ||
/** | ||
* Returns next available ID or throws error (assertion) if no further IDs | ||
* are currently available. Emits {@link EVENT_ADDED} if successful. | ||
*/ | ||
next(): number; | ||
/** | ||
* Marks given ID as available again and increases its version (if | ||
* versioning is enabled). Emits {@link EVENT_REMOVED} if successful. | ||
* | ||
* @param id - | ||
*/ | ||
free(id: number): boolean; | ||
/** | ||
* Returns true iff the given ID is valid and currently used. | ||
* | ||
* @param id - | ||
*/ | ||
has(id: number): boolean; | ||
/** {@inheritDoc @thi.ng/api#INotify.addListener} */ | ||
addListener(id: string, fn: Listener, scope?: any): boolean; | ||
/** {@inheritDoc @thi.ng/api#INotify.removeListener} */ | ||
removeListener(id: string, fn: Listener, scope?: any): boolean; | ||
/** {@inheritDoc @thi.ng/api#INotify.notify} */ | ||
notify(event: Event): boolean; | ||
protected nextVersion(id: number): number; | ||
} | ||
/** | ||
* Returns a new {@link IDGen} instance configured to use given counter & | ||
* version bits. | ||
* | ||
* @remarks | ||
* Overall ID range/capacity can be explicitly limited using `cap` (default and | ||
* maximum: 2^bits). The start ID can be defined via `start` (default: 0) and | ||
* MUST be < `cap`. | ||
* | ||
* @param bits - | ||
* @param vbits - | ||
* @param cap - | ||
* @param start - | ||
*/ | ||
export declare const idgen: (bits: number, vbits?: number, cap?: number, start?: number) => IDGen; | ||
export * from "./api.js"; | ||
export * from "./idgen.js"; | ||
export * from "./monotonic.js"; | ||
export * from "./prefixed.js"; | ||
//# sourceMappingURL=index.d.ts.map |
174
index.js
@@ -1,170 +0,4 @@ | ||
import { __decorate } from "tslib"; | ||
import { INotifyMixin } from "@thi.ng/api/mixins/inotify"; | ||
import { assert } from "@thi.ng/errors/assert"; | ||
export const EVENT_ADDED = "added"; | ||
export const EVENT_REMOVED = "removed"; | ||
export let IDGen = class IDGen { | ||
constructor(bits = 32, vbits = 32 - bits, cap = 2 ** bits, start = 0) { | ||
const maxCap = 2 ** bits; | ||
assert(bits > 0 && bits + vbits <= 32, "wrong total bit size [1..32]"); | ||
assert(cap <= maxCap, `requested capacity too large for bit size (max. ${maxCap})`); | ||
this.ids = []; | ||
this.nextID = start; | ||
this.start = start; | ||
this._capacity = cap; | ||
this.num = 0; | ||
this.mask = maxCap - 1; | ||
this.vmask = (1 << vbits) - 1; | ||
this.shift = bits; | ||
this._freeID = -1; | ||
} | ||
/** | ||
* Extract actual ID (without version bits). | ||
* | ||
* @param id - | ||
*/ | ||
id(id) { | ||
return id & this.mask; | ||
} | ||
/** | ||
* Extract version from ID | ||
* | ||
* @param id - | ||
*/ | ||
version(id) { | ||
return (id >>> this.shift) & this.vmask; | ||
} | ||
get capacity() { | ||
return this._capacity; | ||
} | ||
/** | ||
* Attempts to set new capacity to given value. Capacity can only be | ||
* increased and the operation is only supported for unversioned | ||
* instances (i.e. vbits = 0). | ||
*/ | ||
set capacity(newCap) { | ||
assert(!this.vmask, "can't change capacity w/ versioning enabled"); | ||
if (newCap >= this.mask + 1) { | ||
const bits = Math.ceil(Math.log2(newCap)); | ||
assert(bits > 0 && bits <= 32, "wrong bit size for new capacity [1..32]"); | ||
this._capacity = newCap; | ||
this.mask = 2 ** bits - 1; | ||
this.shift = bits; | ||
} | ||
else { | ||
throw new Error("can't reduce capacity"); | ||
} | ||
} | ||
/** | ||
* Number of remaining available IDs. | ||
*/ | ||
get available() { | ||
return this._capacity - this.num - this.start; | ||
} | ||
/** | ||
* Number of currently used IDs. | ||
*/ | ||
get used() { | ||
return this.num; | ||
} | ||
/** | ||
* Next available free ID. | ||
*/ | ||
get freeID() { | ||
return this._freeID; | ||
} | ||
*[Symbol.iterator]() { | ||
const { ids, mask } = this; | ||
for (let i = this.nextID; i-- > 0;) { | ||
const id = ids[i]; | ||
if ((id & mask) === i) | ||
yield id; | ||
} | ||
} | ||
/** | ||
* Frees all existing IDs and resets counter to original start ID. | ||
*/ | ||
clear() { | ||
this.ids.length = 0; | ||
this.nextID = this.start; | ||
this.num = 0; | ||
this._freeID = -1; | ||
} | ||
/** | ||
* Returns next available ID or throws error (assertion) if no further IDs | ||
* are currently available. Emits {@link EVENT_ADDED} if successful. | ||
*/ | ||
next() { | ||
let id; | ||
if (this._freeID !== -1) { | ||
id = this._freeID; | ||
const rawID = id & this.mask; | ||
this._freeID = this.ids[rawID]; | ||
this.ids[rawID] = id; | ||
} | ||
else { | ||
assert(this.nextID < this._capacity, "max capacity reached"); | ||
id = this.nextID++; | ||
this.ids[id] = id; | ||
} | ||
this.num++; | ||
this.notify({ id: EVENT_ADDED, target: this, value: id }); | ||
return id; | ||
} | ||
/** | ||
* Marks given ID as available again and increases its version (if | ||
* versioning is enabled). Emits {@link EVENT_REMOVED} if successful. | ||
* | ||
* @param id - | ||
*/ | ||
free(id) { | ||
if (!this.has(id)) | ||
return false; | ||
this.ids[id & this.mask] = this._freeID; | ||
this._freeID = this.nextVersion(id); | ||
this.num--; | ||
this.notify({ id: EVENT_REMOVED, target: this, value: id }); | ||
return true; | ||
} | ||
/** | ||
* Returns true iff the given ID is valid and currently used. | ||
* | ||
* @param id - | ||
*/ | ||
has(id) { | ||
const rawID = id & this.mask; | ||
return id >= 0 && rawID < this.nextID && this.ids[rawID] === id; | ||
} | ||
/** {@inheritDoc @thi.ng/api#INotify.addListener} */ | ||
// @ts-ignore: mixin | ||
addListener(id, fn, scope) { } | ||
/** {@inheritDoc @thi.ng/api#INotify.removeListener} */ | ||
// @ts-ignore: mixin | ||
removeListener(id, fn, scope) { } | ||
/** {@inheritDoc @thi.ng/api#INotify.notify} */ | ||
// @ts-ignore: mixin | ||
notify(event) { } | ||
nextVersion(id) { | ||
return (((id & this.mask) | | ||
(((this.version(id) + 1) & this.vmask) << this.shift)) >>> | ||
0); | ||
} | ||
}; | ||
IDGen = __decorate([ | ||
INotifyMixin | ||
], IDGen); | ||
/** | ||
* Returns a new {@link IDGen} instance configured to use given counter & | ||
* version bits. | ||
* | ||
* @remarks | ||
* Overall ID range/capacity can be explicitly limited using `cap` (default and | ||
* maximum: 2^bits). The start ID can be defined via `start` (default: 0) and | ||
* MUST be < `cap`. | ||
* | ||
* @param bits - | ||
* @param vbits - | ||
* @param cap - | ||
* @param start - | ||
*/ | ||
export const idgen = (bits, vbits, cap, start) => new IDGen(bits, vbits, cap, start); | ||
export * from "./api.js"; | ||
export * from "./idgen.js"; | ||
export * from "./monotonic.js"; | ||
export * from "./prefixed.js"; |
{ | ||
"name": "@thi.ng/idgen", | ||
"version": "2.1.34", | ||
"version": "2.2.0", | ||
"description": "Generator of opaque numeric identifiers with optional support for ID versioning and efficient re-use", | ||
@@ -37,13 +37,13 @@ "type": "module", | ||
"dependencies": { | ||
"@thi.ng/api": "^8.8.2", | ||
"@thi.ng/errors": "^2.2.17", | ||
"tslib": "^2.5.3" | ||
"@thi.ng/api": "^8.9.0", | ||
"@thi.ng/errors": "^2.3.0", | ||
"tslib": "^2.6.1" | ||
}, | ||
"devDependencies": { | ||
"@microsoft/api-extractor": "^7.35.3", | ||
"@thi.ng/testament": "^0.3.17", | ||
"@microsoft/api-extractor": "^7.36.3", | ||
"@thi.ng/testament": "^0.3.18", | ||
"rimraf": "^5.0.1", | ||
"tools": "^0.0.1", | ||
"typedoc": "^0.24.8", | ||
"typescript": "^5.1.3" | ||
"typescript": "^5.1.6" | ||
}, | ||
@@ -72,2 +72,14 @@ "keywords": [ | ||
"default": "./index.js" | ||
}, | ||
"./api": { | ||
"default": "./api.js" | ||
}, | ||
"./idgen": { | ||
"default": "./idgen.js" | ||
}, | ||
"./monotonic": { | ||
"default": "./monotonic.js" | ||
}, | ||
"./prefixed": { | ||
"default": "./prefixed.js" | ||
} | ||
@@ -82,3 +94,3 @@ }, | ||
}, | ||
"gitHead": "54e825a976c72067a244cff8725ca98f5416d26d\n" | ||
"gitHead": "9fa3f7f8169efa30e3c71b43c82f77393581c3b5\n" | ||
} |
@@ -17,2 +17,3 @@ <!-- This file is generated - DO NOT EDIT! --> | ||
- [Dependencies](#dependencies) | ||
- [Usage examples](#usage-examples) | ||
- [API](#api) | ||
@@ -79,3 +80,3 @@ - [ID generator with 16 bit range and no versioning](#id-generator-with-16-bit-range-and-no-versioning) | ||
Package sizes (brotli'd, pre-treeshake): ESM: 792 bytes | ||
Package sizes (brotli'd, pre-treeshake): ESM: 990 bytes | ||
@@ -88,2 +89,14 @@ ## Dependencies | ||
## Usage examples | ||
Several demos in this repo's | ||
[/examples](https://github.com/thi-ng/umbrella/tree/develop/examples) | ||
directory are using this package. | ||
A selection: | ||
| Screenshot | Description | Live demo | Source | | ||
|:--------------------------------------------------------------------------------------------------------------------|:--------------------------------------------|:---------------------------------------------------|:--------------------------------------------------------------------------------| | ||
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/fiber-basics.png" width="240"/> | Fiber-based cooperative multitasking basics | [Demo](https://demo.thi.ng/umbrella/fiber-basics/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/fiber-basics) | | ||
## API | ||
@@ -90,0 +103,0 @@ |
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
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
37761
14
421
218
1
Updated@thi.ng/api@^8.9.0
Updated@thi.ng/errors@^2.3.0
Updatedtslib@^2.6.1