Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@thi.ng/idgen

Package Overview
Dependencies
Maintainers
1
Versions
143
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@thi.ng/idgen - npm Package Compare versions

Comparing version 2.2.14 to 2.2.15

8

api.js

@@ -1,2 +0,6 @@

export const EVENT_ADDED = "added";
export const EVENT_REMOVED = "removed";
const EVENT_ADDED = "added";
const EVENT_REMOVED = "removed";
export {
EVENT_ADDED,
EVENT_REMOVED
};
# Change Log
- **Last updated**: 2023-12-09T19:12:03Z
- **Last updated**: 2023-12-11T10:07:09Z
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)

@@ -5,0 +5,0 @@

@@ -1,181 +0,185 @@

import { __decorate } from "tslib";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
for (var i = decorators.length - 1, decorator; i >= 0; i--)
if (decorator = decorators[i])
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
if (kind && result)
__defProp(target, key, result);
return result;
};
import { INotifyMixin } from "@thi.ng/api/mixins/inotify";
import { assert } from "@thi.ng/errors/assert";
import { EVENT_ADDED, EVENT_REMOVED } from "./api.js";
let IDGen = class IDGen {
ids;
nextID;
_freeID;
start;
num;
_capacity;
mask;
vmask;
shift;
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;
let IDGen = class {
ids;
nextID;
_freeID;
start;
num;
_capacity;
mask;
vmask;
shift;
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");
}
/**
* Extract actual ID (without version bits).
*
* @param id -
*/
id(id) {
return id & this.mask;
}
/**
* 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;
}
/**
* Extract version from ID
*
* @param id -
*/
version(id) {
return (id >>> this.shift) & this.vmask;
}
/**
* 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;
}
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
// prettier-ignore
addListener(id, fn, scope) { }
/** {@inheritDoc @thi.ng/api#INotify.removeListener} */
// @ts-ignore: mixin
// prettier-ignore
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);
}
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
// prettier-ignore
addListener(id, fn, scope) {
}
/** {@inheritDoc @thi.ng/api#INotify.removeListener} */
// @ts-ignore: mixin
// prettier-ignore
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 = __decorateClass([
INotifyMixin
], IDGen);
export { 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);
const idgen = (bits, vbits, cap, start) => new IDGen(bits, vbits, cap, start);
export {
IDGen,
idgen
};

@@ -1,56 +0,56 @@

import { __decorate } from "tslib";
import { INotifyMixin, } from "@thi.ng/api";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
for (var i = decorators.length - 1, decorator; i >= 0; i--)
if (decorator = decorators[i])
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
if (kind && result)
__defProp(target, key, result);
return result;
};
import {
INotifyMixin
} from "@thi.ng/api";
import { assert } from "@thi.ng/errors/assert";
import { EVENT_ADDED, EVENT_REMOVED } from "./api.js";
/**
* Simple monotonically increasing numeric ID generator. Unbounded and depending
* on numeric range covered, inprecise (e.g. for values outside the JS safe
* integer range).
*
* Unlike {@link IDGen}, this class doesn't keep track of generated IDs and the
* {@link MonotonicID.free} implementation only checks if a given ID could
* possibly already have been generated.
*/
let MonotonicID = class MonotonicID {
start;
step;
nextID;
constructor(start = 0, step = 1) {
this.start = start;
this.step = step;
assert(step > 0, "invalid step size");
this.nextID = start;
}
next() {
const id = this.nextID;
this.nextID += this.step;
this.notify({ id: EVENT_ADDED, target: this, value: id });
return id;
}
free(id) {
if (!(id >= this.start && id < this.nextID))
return false;
this.notify({ id: EVENT_REMOVED, target: this, value: id });
return true;
}
// @ts-ignore: mixin
// prettier-ignore
addListener(id, fn, scope) { }
// @ts-ignore: mixin
// prettier-ignore
removeListener(id, fn, scope) { }
// @ts-ignore: mixin
notify(event) { }
let MonotonicID = class {
constructor(start = 0, step = 1) {
this.start = start;
this.step = step;
assert(step > 0, "invalid step size");
this.nextID = start;
}
nextID;
next() {
const id = this.nextID;
this.nextID += this.step;
this.notify({ id: EVENT_ADDED, target: this, value: id });
return id;
}
free(id) {
if (!(id >= this.start && id < this.nextID))
return false;
this.notify({ id: EVENT_REMOVED, target: this, value: id });
return true;
}
// @ts-ignore: mixin
// prettier-ignore
addListener(id, fn, scope) {
}
// @ts-ignore: mixin
// prettier-ignore
removeListener(id, fn, scope) {
}
// @ts-ignore: mixin
notify(event) {
}
};
MonotonicID = __decorate([
INotifyMixin
MonotonicID = __decorateClass([
INotifyMixin
], MonotonicID);
export { MonotonicID };
/**
* Returns a new {@link MonotonicID} instance with given `start` offset
* (default: 0) and `step` size (default: 1).
*
* @param start
* @param step
*/
export const monotonic = (start, step) => new MonotonicID(start, step);
const monotonic = (start, step) => new MonotonicID(start, step);
export {
MonotonicID,
monotonic
};
{
"name": "@thi.ng/idgen",
"version": "2.2.14",
"version": "2.2.15",
"description": "Generator of opaque numeric identifiers with optional support for ID versioning and efficient re-use",

@@ -27,3 +27,5 @@ "type": "module",

"scripts": {
"build": "yarn clean && tsc --declaration",
"build": "yarn build:esbuild && yarn build:decl",
"build:decl": "tsc --declaration --emitDeclarationOnly",
"build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
"clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc",

@@ -37,4 +39,4 @@ "doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",

"dependencies": {
"@thi.ng/api": "^8.9.11",
"@thi.ng/errors": "^2.4.5",
"@thi.ng/api": "^8.9.12",
"@thi.ng/errors": "^2.4.6",
"tslib": "^2.6.2"

@@ -44,2 +46,3 @@ },

"@microsoft/api-extractor": "^7.38.3",
"esbuild": "^0.19.8",
"rimraf": "^5.0.5",

@@ -93,3 +96,3 @@ "tools": "^0.0.1",

},
"gitHead": "25f2ac8ff795a432a930119661b364d4d93b59a0\n"
"gitHead": "5e7bafedfc3d53bc131469a28de31dd8e5b4a3ff\n"
}

@@ -1,45 +0,51 @@

import { __decorate } from "tslib";
import { INotifyMixin, } from "@thi.ng/api";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
for (var i = decorators.length - 1, decorator; i >= 0; i--)
if (decorator = decorators[i])
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
if (kind && result)
__defProp(target, key, result);
return result;
};
import {
INotifyMixin
} from "@thi.ng/api";
import { EVENT_ADDED, EVENT_REMOVED } from "./api.js";
/**
* Wrapped ID generator for creating string-based IDs derived from a backing ID gen.
*/
let PrefixedID = class PrefixedID {
prefix;
gen;
constructor(prefix, gen) {
this.prefix = prefix;
this.gen = gen;
}
next() {
const id = this.prefix + this.gen.next();
this.notify({ id: EVENT_ADDED, target: this, value: id });
return id;
}
free(id) {
if (!(id.startsWith(this.prefix) &&
this.gen.free(Number(id.substring(this.prefix.length)))))
return false;
this.notify({ id: EVENT_REMOVED, target: this, value: id });
return true;
}
// @ts-ignore: mixin
// prettier-ignore
addListener(id, fn, scope) { }
// @ts-ignore: mixin
// prettier-ignore
removeListener(id, fn, scope) { }
// @ts-ignore: mixin
notify(event) { }
let PrefixedID = class {
constructor(prefix, gen) {
this.prefix = prefix;
this.gen = gen;
}
next() {
const id = this.prefix + this.gen.next();
this.notify({ id: EVENT_ADDED, target: this, value: id });
return id;
}
free(id) {
if (!(id.startsWith(this.prefix) && this.gen.free(Number(id.substring(this.prefix.length)))))
return false;
this.notify({ id: EVENT_REMOVED, target: this, value: id });
return true;
}
// @ts-ignore: mixin
// prettier-ignore
addListener(id, fn, scope) {
}
// @ts-ignore: mixin
// prettier-ignore
removeListener(id, fn, scope) {
}
// @ts-ignore: mixin
notify(event) {
}
};
PrefixedID = __decorate([
INotifyMixin
PrefixedID = __decorateClass([
INotifyMixin
], PrefixedID);
export { PrefixedID };
/**
* Syntax sugar for {@link PrefixedID} constructor.
*
* @param prefix
* @param gen
*/
export const prefixed = (prefix, gen) => new PrefixedID(prefix, gen);
const prefixed = (prefix, gen) => new PrefixedID(prefix, gen);
export {
PrefixedID,
prefixed
};

@@ -80,3 +80,3 @@ <!-- This file is generated - DO NOT EDIT! -->

Package sizes (brotli'd, pre-treeshake): ESM: 1.09 KB
Package sizes (brotli'd, pre-treeshake): ESM: 1.18 KB

@@ -83,0 +83,0 @@ ## Dependencies

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc