@alttiri/util-js
Advanced tools
Comparing version 1.9.2-20240524 to 1.10.0-20240531
export type * from "./src/sync/VoidFunc"; | ||
export * from "./src/sync/Semaphore"; | ||
export * from "./src/sync/CountLatch"; | ||
export * from "./src/sync/AsyncBufferQueue"; | ||
export * from "./src/sync/Queue"; | ||
export * from "./src/sync/Semaphore"; | ||
export * from "./src/sync/CountLatch"; | ||
export * from "./src/sync/AsyncBufferQueue"; | ||
export * from "./src/sync/Queue"; | ||
export type * from "./src/sync/Queue"; | ||
export * from "./src/byte-size-converter"; | ||
@@ -9,0 +8,0 @@ export * from "./src/date-formatter"; |
19
index.js
@@ -1,11 +0,8 @@ | ||
// --- | ||
export * from "./src/sync/Semaphore.js"; | ||
export * from "./src/sync/CountLatch.js"; | ||
export * from "./src/sync/AsyncBufferQueue.js"; | ||
export * from "./src/sync/Queue.js"; | ||
// --- | ||
export * from "./src/byte-size-converter.js"; | ||
export * from "./src/date-formatter.js"; | ||
export * from "./src/sleep.js"; | ||
export * from "./src/util.js"; | ||
export * from "./src/sync/Semaphore"; | ||
export * from "./src/sync/CountLatch"; | ||
export * from "./src/sync/AsyncBufferQueue"; | ||
export * from "./src/sync/Queue"; | ||
export * from "./src/byte-size-converter"; | ||
export * from "./src/date-formatter"; | ||
export * from "./src/sleep"; | ||
export * from "./src/util"; |
{ | ||
"name": "@alttiri/util-js", | ||
"version": "1.9.2-20240524", | ||
"version": "1.10.0-20240531", | ||
"description": "Some util functions for personal use", | ||
@@ -19,3 +19,4 @@ "homepage": "https://github.com/AlttiRi/util-js", | ||
"files": [ | ||
"src", | ||
"src/**/*.js", | ||
"src/**/*.d.ts", | ||
"index.js", | ||
@@ -33,7 +34,12 @@ "index.d.ts" | ||
"scripts": { | ||
"publish-npm": "npm publish --registry=https://registry.npmjs.org", | ||
"publish-ghp": "npm publish --registry=https://npm.pkg.github.com", | ||
"compile-ts": "tsc --build", | ||
"compile-ts-watch": "tsc --build --watch", | ||
"clean-ts": "tsc --build --clean", | ||
"#": "", | ||
"publish-npm": "npm publish --registry=https://registry.npmjs.org", | ||
"publish-ghp": "npm publish --registry=https://npm.pkg.github.com", | ||
"test-publish": "npm pack", | ||
"##": "", | ||
"unpublish-npm": "npm unpublish @alttiri/util-js@1.8.3 --registry=https://registry.npmjs.org", | ||
"##": "", | ||
"###": "", | ||
"login-npm": "npm login --registry=https://registry.npmjs.org", | ||
@@ -43,4 +49,5 @@ "login-ghp": "npm login --registry=https://npm.pkg.github.com" | ||
"devDependencies": { | ||
"@alttiri/util-node-js": "1.6.0" | ||
"@alttiri/util-node-js": "2.0.10-20240530", | ||
"typescript": "5.4.5" | ||
} | ||
} |
@@ -1,7 +0,32 @@ | ||
export function formatSizeWinLike(bytes: number): string; | ||
export {formatSizeWinLike as bytesToSizeWinLike}; | ||
export function toTruncPrecision3(number: number): string; | ||
export function formatNumber(num: number): string; | ||
export {formatNumber as tripleSizeGroups}; | ||
/** @deprecated */ | ||
export { formatSizeWinLike as bytesToSizeWinLike }; | ||
/** | ||
* Formats bytes mostly like Windows does, | ||
* but in some rare cases the result is different. | ||
* Check the file with tests. | ||
* @see format-size-win-like.test.js | ||
* @param {number} bytes | ||
* @return {string} | ||
*/ | ||
export declare function formatSizeWinLike(bytes: number): string; | ||
/** | ||
* @example | ||
* 10.1005859375 -> "10.1" | ||
* 9.99902343750 -> "9.99" | ||
* 836.966796875 -> "836" | ||
* 0.08 -> "0.08" | ||
* 0.099 -> "0.09" | ||
* 0.0099 -> "0" | ||
* @param {number} number | ||
* @return {string} | ||
*/ | ||
export declare function toTruncPrecision3(number: number): string; | ||
/** @deprecated */ | ||
export { formatNumber as tripleSizeGroups }; | ||
/** | ||
* Useful for file byte size formatting: | ||
* 34456909 -> 34 456 909 | ||
* @param {number} num | ||
* @return {string} | ||
* */ | ||
export declare function formatNumber(num: number): string; |
/** @deprecated */ | ||
export {formatSizeWinLike as bytesToSizeWinLike}; // The old name | ||
export { formatSizeWinLike as bytesToSizeWinLike }; // The old name | ||
/** | ||
@@ -13,3 +12,5 @@ * Formats bytes mostly like Windows does, | ||
export function formatSizeWinLike(bytes) { | ||
if (bytes < 1024) { return bytes + " B"; } | ||
if (bytes < 1024) { | ||
return bytes + " B"; | ||
} | ||
const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; | ||
@@ -24,4 +25,10 @@ let i = Math.floor(Math.log(bytes) / Math.log(1024)); | ||
} | ||
/** | ||
* @example | ||
* 10.1005859375 -> "10.1" | ||
* 9.99902343750 -> "9.99" | ||
* 836.966796875 -> "836" | ||
* 0.08 -> "0.08" | ||
* 0.099 -> "0.09" | ||
* 0.0099 -> "0" | ||
* @param {number} number | ||
@@ -34,10 +41,16 @@ * @return {string} | ||
result = Math.trunc(number * 100) / 100; | ||
} else if (number < 100) { | ||
} | ||
else if (number < 100) { | ||
result = Math.trunc(number * 10) / 10; | ||
} else if (number < 1000) { | ||
} | ||
else if (number < 1000) { | ||
result = Math.trunc(number); | ||
} | ||
else { | ||
return Math.trunc(number).toString(); | ||
} | ||
if (number < 0.1) { | ||
return result.toPrecision(1); | ||
} else if (number < 1) { | ||
} | ||
else if (number < 1) { | ||
return result.toPrecision(2); | ||
@@ -47,6 +60,4 @@ } | ||
} | ||
/** @deprecated */ | ||
export {formatNumber as tripleSizeGroups}; // The old name | ||
export { formatNumber as tripleSizeGroups }; // The old name | ||
/** | ||
@@ -60,3 +71,11 @@ * Useful for file byte size formatting: | ||
const str = num.toString(); | ||
return str.padStart(str.length + (3 - str.length % 3)).match(/(.{3})/g).join(" ").trimStart(); | ||
const maxLength = str.length + (3 - str.length % 3); | ||
const result = str.padStart(maxLength, " ") | ||
.match(/(.{3})/g) | ||
.join(" ") | ||
.trimStart(); | ||
if (num < 0) { | ||
return result.replace(/^- /, "-"); | ||
} | ||
return result; | ||
} |
/** | ||
* "Sun, 10 Jan 2021 22:22:22 GMT" -> "2021.01.10" | ||
* @param {(Date | string | number)?} dateValue | ||
* @param {boolean} utc = true | ||
* @param {Date | string | number?} [dateValue] | ||
* @param {boolean} [utc = true] | ||
* @return {string} | ||
*/ | ||
export function dateToDayDateString(dateValue?: Date | string | number, utc?: boolean): string; | ||
export declare function dateToDayDateString(dateValue?: Date | string | number, utc?: boolean): string; | ||
/** | ||
* "Sun, 10 Jan 2021 22:22:22 GMT" -> "2021.01.10 22:22:22Z" | ||
* @param {(Date | string | number)?} dateValue | ||
* @param {boolean?} utc = true | ||
* @param {Date | string | number} [dateValue] | ||
* @param {boolean?} [utc = true] | ||
* @return {string} | ||
*/ | ||
export function dateToDayDateTimeString(dateValue?: Date | string | number, utc?: boolean): string; | ||
export declare function dateToDayDateTimeString(dateValue?: Date | string | number, utc?: boolean): string; | ||
/** | ||
* "Sun, 10 Jan 2021 22:22:22 GMT" -> "2021.01.10 22:22:22" | ||
* @param {(Date | string | number)?} dateValue | ||
* @param {Date | string | number} [dateValue] | ||
* @return {string} | ||
*/ | ||
export function localDate(dateValue: number | string | Date): string { | ||
return dateToDayDateString(dateValue, false); | ||
} | ||
export declare function localDate(dateValue?: number | string | Date): string; | ||
/** | ||
* "Sun, 10 Jan 2021 22:22:22 GMT" -> "2021.01.10" | ||
* @param {(Date | string | number)?} dateValue | ||
* @param {Date | string | number} [dateValue] | ||
* @return {string} | ||
*/ | ||
export function localDateTime(dateValue: number | string | Date): string { | ||
return dateToDayDateTimeString(dateValue, false); | ||
} | ||
export declare function localDateTime(dateValue?: number | string | Date): string; | ||
/** | ||
* Formats date. Supports: YY.YYYY.MM.DD HH:mm:SS. | ||
* Default format: "YYYY.MM.DD". formatDate() -> "2022.01.07" | ||
* @param {(Date | string | number)?} dateValue | ||
* @param {string?} pattern | ||
* @param {boolean?} utc | ||
* Default format: "YYYY.MM.DD". | ||
* formatDate() -> "2022.01.07" | ||
* @param {Date | string | number} [dateValue] | ||
* @param {string} [pattern = "YYYY.MM.DD"] | ||
* @param {boolean} [utc = true] | ||
* @return {string} | ||
*/ | ||
export function formatDate(dateValue?: Date | string | number, pattern?: string, utc?: boolean): string; | ||
export declare function formatDate(dateValue?: Date | string | number, pattern?: string, utc?: boolean): string; |
@@ -0,5 +1,6 @@ | ||
import { isString } from "./util"; | ||
/** | ||
* "Sun, 10 Jan 2021 22:22:22 GMT" -> "2021.01.10" | ||
* @param {(Date | string | number)?} dateValue | ||
* @param {boolean} utc = true | ||
* @param {Date | string | number?} [dateValue] | ||
* @param {boolean} [utc = true] | ||
* @return {string} | ||
@@ -10,7 +11,6 @@ */ | ||
} | ||
/** | ||
* "Sun, 10 Jan 2021 22:22:22 GMT" -> "2021.01.10 22:22:22Z" | ||
* @param {(Date | string | number)?} dateValue | ||
* @param {boolean?} utc = true | ||
* @param {Date | string | number} [dateValue] | ||
* @param {boolean?} [utc = true] | ||
* @return {string} | ||
@@ -21,6 +21,5 @@ */ | ||
} | ||
/** | ||
* "Sun, 10 Jan 2021 22:22:22 GMT" -> "2021.01.10 22:22:22" | ||
* @param {(Date | string | number)?} dateValue | ||
* @param {Date | string | number} [dateValue] | ||
* @return {string} | ||
@@ -33,15 +32,15 @@ */ | ||
* "Sun, 10 Jan 2021 22:22:22 GMT" -> "2021.01.10" | ||
* @param {(Date | string | number)?} dateValue | ||
* @param {Date | string | number} [dateValue] | ||
* @return {string} | ||
*/ | ||
export function localDateTime(dateValue){ | ||
export function localDateTime(dateValue) { | ||
return dateToDayDateTimeString(dateValue, false); | ||
} | ||
/** | ||
* Formats date. Supports: YY.YYYY.MM.DD HH:mm:SS. | ||
* Default format: "YYYY.MM.DD". formatDate() -> "2022.01.07" | ||
* @param {(Date | string | number)?} dateValue | ||
* @param {string?} pattern | ||
* @param {boolean?} utc | ||
* Default format: "YYYY.MM.DD". | ||
* formatDate() -> "2022.01.07" | ||
* @param {Date | string | number} [dateValue] | ||
* @param {string} [pattern = "YYYY.MM.DD"] | ||
* @param {boolean} [utc = true] | ||
* @return {string} | ||
@@ -56,11 +55,12 @@ */ | ||
const formatter = new DateFormatter(date, utc); | ||
return pattern.replaceAll(/YYYY|YY|MM|DD|HH|mm|SS/g, (...args) => formatter[args[0]]); | ||
return pattern.replaceAll(/YYYY|YY|MM|DD|HH|mm|SS/g, (...args) => { | ||
const property = args[0]; | ||
return formatter[property]; | ||
}); | ||
} | ||
/** @return {boolean} */ | ||
function isString(input) { | ||
return typeof input === "string" || input instanceof String; | ||
} | ||
function firefoxDateFix(dateValue) { | ||
return isString(dateValue) ? dateValue.replace(/(?<y>\d{4})\.(?<m>\d{2})\.(?<d>\d{2})/, "$<y>-$<m>-$<d>") : dateValue; | ||
if (isString(dateValue)) { | ||
return dateValue.replace(/(?<y>\d{4})\.(?<m>\d{2})\.(?<d>\d{2})/, "$<y>-$<m>-$<d>"); | ||
} | ||
return dateValue; | ||
} | ||
@@ -76,10 +76,9 @@ /** @return {string} */ | ||
} | ||
get SS() {return pad0(this.date[`get${this.utc}Seconds`]())} | ||
get mm() {return pad0(this.date[`get${this.utc}Minutes`]())} | ||
get HH() {return pad0(this.date[`get${this.utc}Hours`]())} | ||
get MM() {return pad0(this.date[`get${this.utc}Month`]() + 1)} | ||
get DD() {return pad0(this.date[`get${this.utc}Date`]())} | ||
get YYYY() {return pad0(this.date[`get${this.utc}FullYear`](), 4)} | ||
get YY() {return this.YYYY.slice(2);} | ||
get SS() { return pad0(this.date[`get${this.utc}Seconds`]()); } | ||
get mm() { return pad0(this.date[`get${this.utc}Minutes`]()); } | ||
get HH() { return pad0(this.date[`get${this.utc}Hours`]()); } | ||
get MM() { return pad0(this.date[`get${this.utc}Month`]() + 1); } | ||
get DD() { return pad0(this.date[`get${this.utc}Date`]()); } | ||
get YYYY() { return pad0(this.date[`get${this.utc}FullYear`](), 4); } | ||
get YY() { return this.YYYY.slice(2); } | ||
} |
@@ -1,1 +0,7 @@ | ||
export function sleep(ms?: number): Promise<void>; | ||
/** | ||
* Sleeps `ms` milliseconds. | ||
* If param is `undefined` it sleeps until the next macro-task. | ||
* Note: With `0` real ms will be `4`+ ms. | ||
* @param {number?} ms | ||
* */ | ||
export declare function sleep(ms?: number): Promise<void>; |
@@ -0,10 +1,11 @@ | ||
// @ts-ignore | ||
const __setImmediate = typeof globalThis.setImmediate === "function" ? globalThis.setImmediate : null; | ||
const setImmediate = __setImmediate || /*#__PURE__*/ (function() { | ||
const {port1, port2} = new MessageChannel(); | ||
const setImmediate = __setImmediate || /*#__PURE__*/ (function () { | ||
const { port1, port2 } = new MessageChannel(); | ||
const queue = []; | ||
port1.onmessage = function() { | ||
port1.onmessage = function () { | ||
const callback = queue.shift(); | ||
callback(); | ||
}; | ||
return function setImmediateLike(callback) { // Simplified implementation: only callback argument. | ||
return function setImmediateLike(callback) { | ||
port2.postMessage(null); | ||
@@ -14,3 +15,2 @@ queue.push(callback); | ||
})(); | ||
/** | ||
@@ -28,3 +28,1 @@ * Sleeps `ms` milliseconds. | ||
} | ||
@@ -1,4 +0,1 @@ | ||
import {Semaphore} from "./Semaphore"; | ||
import {VoidFunc} from "./VoidFunc"; | ||
/** | ||
@@ -13,12 +10,12 @@ * Use it when in one place you need to `enqueue()` some `value`, until `close()`. | ||
*/ | ||
export class AsyncBufferQueue<T> { | ||
private values: T[]; | ||
private done: boolean; | ||
private promise: Promise<void>; | ||
private resolve: VoidFunc; | ||
private semaphore: Semaphore; | ||
constructor(size: number = 128); | ||
export declare class AsyncBufferQueue<T> { | ||
private values; | ||
private done; | ||
private promise; | ||
private resolve; | ||
private semaphore; | ||
constructor(size?: number); | ||
close(): void; | ||
async enqueue(value: T): Promise<void>; | ||
async *[Symbol.asyncIterator](): AsyncGenerator<T>; | ||
enqueue(value: T): Promise<void>; | ||
[Symbol.asyncIterator](): AsyncGenerator<T>; | ||
} |
@@ -1,3 +0,11 @@ | ||
import {Semaphore} from "./Semaphore.js"; | ||
import { Semaphore } from "./Semaphore"; | ||
/** | ||
* Use it when in one place you need to `enqueue()` some `value`, until `close()`. | ||
* In other place you can iterate over this queue in for-await loop. | ||
* | ||
* `enqueue` does not add a value until there is a free space in the queue, you should `await` it. | ||
* (`size` parameter of `constructor`). | ||
* | ||
* Use `close()` after you finished to `enqueue()` data. | ||
*/ | ||
export class AsyncBufferQueue { | ||
@@ -4,0 +12,0 @@ constructor(size = 128) { |
@@ -1,12 +0,12 @@ | ||
import {VoidFunc} from "./VoidFunc"; | ||
export class CountLatch { | ||
private count: number; | ||
private promise: Promise<void>; | ||
private resolve: VoidFunc; | ||
constructor(count?); | ||
import { VoidFunc } from "./VoidFunc"; | ||
export declare class CountLatch { | ||
private count; | ||
private promise; | ||
private resolve; | ||
/** @param {number} count = 0 */ | ||
constructor(count?: number); | ||
countDown(): void; | ||
countUp(): void; | ||
then(resolve: VoidFunc, reject: VoidFunc): Promise<void> | ||
/** Makes this object "Thenable" */ | ||
then(resolve: VoidFunc, reject: VoidFunc): Promise<void>; | ||
} |
@@ -10,3 +10,3 @@ export class CountLatch { | ||
/** @type {VoidFunc} */ | ||
this.resolve = () => {}; | ||
this.resolve = () => { }; | ||
return; | ||
@@ -18,3 +18,2 @@ } | ||
} | ||
countDown() { | ||
@@ -28,3 +27,2 @@ if (this.count > 0) { | ||
} | ||
countUp() { | ||
@@ -38,7 +36,6 @@ if (this.count === 0) { | ||
} | ||
/** Makes this object "Thenable" */ | ||
then(resolve, reject) { | ||
this.promise.then(resolve, reject); | ||
return this.promise.then(resolve, reject); | ||
} | ||
} |
export type Node<T> = { | ||
value: T, | ||
next: Node<T> | null, | ||
value: T; | ||
next: Node<T> | null; | ||
}; | ||
/** "LinkedList" with `Array` interface */ | ||
export class Queue<T> { | ||
public length = 0; | ||
private _last: Node<T> | null = null; | ||
private _first: Node<T> | null = null; | ||
push(value: T); | ||
export declare class Queue<T> { | ||
length: number; | ||
private _last; | ||
private _first; | ||
constructor(); | ||
push(value: T): void; | ||
shift(): T | undefined; | ||
} |
@@ -0,1 +1,2 @@ | ||
/** "LinkedList" with `Array` interface */ | ||
export class Queue { | ||
@@ -6,2 +7,5 @@ constructor() { | ||
this._first = null; | ||
this.length = 0; | ||
this._last = null; | ||
this._first = null; | ||
} | ||
@@ -8,0 +12,0 @@ push(value) { |
@@ -1,11 +0,12 @@ | ||
import {VoidFunc} from "./VoidFunc"; | ||
/** The most simple semaphore implementation. */ | ||
export declare class Semaphore { | ||
private readonly max: number; | ||
private count: number; | ||
private readonly resolveQueue: VoidFunc[]; | ||
private readonly max; | ||
private count; | ||
private readonly resolveQueue; | ||
/** @param {number} [max = 1] - by default, it works as a mutex. */ | ||
constructor(max?: number); | ||
acquire(): Promise<void>; | ||
/** @return {Promise<unknown>} */ | ||
acquire(): Promise<unknown>; | ||
/** @return {void} */ | ||
release(): void; | ||
} |
/** The most simple semaphore implementation. */ | ||
export class Semaphore { | ||
/** @param {number} max = 1 - by default, it works as a mutex. */ | ||
/** @param {number} [max = 1] - by default, it works as a mutex. */ | ||
constructor(max = 1) { | ||
@@ -8,11 +8,7 @@ if (max < 1) { | ||
} | ||
/** @type {number} */ | ||
this.max = max; | ||
/** @type {number} */ | ||
this.count = 0; | ||
/** @type {VoidFunc[]} */ | ||
this.resolveQueue = []; | ||
} | ||
/** @return {Promise<void>} */ | ||
/** @return {Promise<unknown>} */ | ||
acquire() { | ||
@@ -22,3 +18,4 @@ let promise; | ||
promise = Promise.resolve(); | ||
} else { | ||
} | ||
else { | ||
promise = new Promise(resolve => { | ||
@@ -25,0 +22,0 @@ this.resolveQueue.push(resolve); |
@@ -1,1 +0,1 @@ | ||
export function isString(value: unknown): value is string; | ||
export declare function isString(value: unknown): value is string; |
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
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
19466
23
488
2