+11
-1
@@ -2,7 +2,17 @@
|
||||
|
||||
All notable changes are documented here.
|
||||
|
||||
## Unreleased
|
||||
## 0.2.0 - 2026-09-02
|
||||
|
||||
- Added deterministic IEC/SI byte-size formatting, checked byte-range
|
||||
arithmetic and a bounded typed byte cursor.
|
||||
- Added cancellable disposable-worker jobs with typed progress, serialized
|
||||
failures, abort propagation and hard client deadlines.
|
||||
- Added explicit Blob URL pools plus deterministic, collision-free multi-file
|
||||
download planning and triggering.
|
||||
- Added incremental CRC-32, Adler-32 and FNV-1a state and bounded Blob,
|
||||
ReadableStream and async-iterable consumption for checksums and Web Crypto
|
||||
digests.
|
||||
|
||||
## 0.1.0 - 2026-09-01
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
==============================================================================
|
||||
@add-ideas/toolbox-contract@0.2.3
|
||||
@add-ideas/toolbox-contract@0.3.0
|
||||
Declared licence: Apache-2.0
|
||||
Installed from: node_modules/@add-ideas/toolbox-contract
|
||||
==============================================================================
|
||||
@@ -199,7 +199,7 @@ Installed from: node_modules/@add-ideas/toolbox-contract
|
||||
|
||||
|
||||
==============================================================================
|
||||
@add-ideas/toolbox-shell-react@0.2.3
|
||||
@add-ideas/toolbox-shell-react@0.3.0
|
||||
Declared licence: Apache-2.0
|
||||
Installed from: node_modules/@add-ideas/toolbox-shell-react
|
||||
==============================================================================
|
||||
|
||||
+17
-2
@@ -5,7 +5,7 @@ Helper Tools is a local-first browser workbench and the source of the
|
||||
bounded building blocks for common developer calculations without network
|
||||
requests, telemetry, persistence, or server processing.
|
||||
|
||||
Version 0.1.0 includes:
|
||||
The reusable package includes:
|
||||
|
||||
- strict Base64, Base64URL, hexadecimal, UTF-8, UTF-16 and Latin-1 conversion;
|
||||
- URL component and form encoding, Unicode scalar/grapheme inspection, case,
|
||||
@@ -16,7 +16,13 @@ Version 0.1.0 includes:
|
||||
- timestamp and bounded duration parsing and formatting;
|
||||
- hardened JSON parsing, deterministic JSON and bounded CSV conversion; and
|
||||
- secure random bytes/integers plus explicitly non-cryptographic seeded random
|
||||
primitives for repeatable tests and samples.
|
||||
primitives for repeatable tests and samples;
|
||||
- checked offset arithmetic and a bounded typed byte cursor for binary parsers;
|
||||
- deterministic byte-size formatting, collision-free multi-file download plans,
|
||||
and explicit Blob URL lease pools;
|
||||
- cancellable disposable-worker jobs with progress and hard deadlines; and
|
||||
- incremental CRC-32, Adler-32 and FNV-1a processing plus bounded,
|
||||
cancellable byte-source reads for Web Crypto digests.
|
||||
|
||||
## Browser app
|
||||
|
||||
@@ -38,8 +44,11 @@ exported from one stable root:
|
||||
|
||||
```ts
|
||||
import {
|
||||
ByteCursor,
|
||||
bytesToBase64Url,
|
||||
createIncrementalChecksum,
|
||||
digestHex,
|
||||
formatBytes,
|
||||
parseCidr,
|
||||
safeJsonParse,
|
||||
} from "@add-ideas/toolbox-helpers";
|
||||
@@ -48,6 +57,12 @@ const token = bytesToBase64Url(new Uint8Array([1, 2, 3]));
|
||||
const hash = await digestHex(new TextEncoder().encode("local"));
|
||||
const network = parseCidr("2001:db8::1/64");
|
||||
const data = safeJsonParse('{"enabled":true}');
|
||||
const size = formatBytes(1_572_864); // 1.50 MiB
|
||||
const cursor = new ByteCursor(new Uint8Array([0, 1, 0, 2]));
|
||||
const first = cursor.readUint16();
|
||||
const checksum = createIncrementalChecksum("CRC-32").update(
|
||||
new Uint8Array([1, 2, 3]),
|
||||
);
|
||||
```
|
||||
|
||||
See [`docs/API.md`](docs/API.md) for the export groups and their security
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
# Corresponding source and provenance
|
||||
|
||||
The corresponding source for Helper Tools 0.1.0 will be published at:
|
||||
The corresponding source for Helper Tools 0.2.0 will be published at:
|
||||
|
||||
https://git.add-ideas.de/lotobo/helper-tools/src/tag/v0.1.0
|
||||
https://git.add-ideas.de/lotobo/helper-tools/src/tag/v0.2.0
|
||||
|
||||
Before that tag exists, the `main` branch in the same public repository is the
|
||||
preferred source under active review. Build the release with Node.js 22 and the
|
||||
@@ -19,7 +19,7 @@ not the preferred form for modification. No runtime code is loaded from a CDN.
|
||||
## Implementation provenance
|
||||
|
||||
- The helpers and interface are original TypeScript and React project code.
|
||||
- Toolbox manifest, shell and artifact checks use the shared Toolbox SDK 0.2.3.
|
||||
- Toolbox manifest, shell and artifact checks use the shared Toolbox SDK 0.3.0.
|
||||
- Encoding formats, IP notation, JSON, CSV, SI/IEC units, Unicode, ISO 8601,
|
||||
checksum and digest algorithms were implemented from public specifications
|
||||
and established interoperable formats; no source from an online calculator
|
||||
|
||||
@@ -5,8 +5,8 @@ browser application uses these packages:
|
||||
|
||||
| Package | Version | Licence | Role |
|
||||
| -------------------------------- | ------- | ---------- | ------------------------------- |
|
||||
| `@add-ideas/toolbox-contract` | 0.2.3 | Apache-2.0 | manifest and context contract |
|
||||
| `@add-ideas/toolbox-shell-react` | 0.2.3 | Apache-2.0 | shared shell, theme and actions |
|
||||
| `@add-ideas/toolbox-contract` | 0.3.0 | Apache-2.0 | manifest and context contract |
|
||||
| `@add-ideas/toolbox-shell-react` | 0.3.0 | Apache-2.0 | shared shell, theme and actions |
|
||||
| `react` | 19.2.8 | MIT | browser interface |
|
||||
| `react-dom` | 19.2.8 | MIT | browser rendering |
|
||||
|
||||
|
||||
@@ -21,6 +21,13 @@ assertBoundedBytes(value: BytesLike, maximum?: number, label?: string): Uint8Arr
|
||||
assertBoundedItems(count: number, maximum?: number, label?: string): number;
|
||||
assertPositiveSafeInteger(value: number, label: string): number;
|
||||
asUint8Array(value: BytesLike): Uint8Array;
|
||||
|
||||
interface ByteRange { offset: number; length: number; end: number }
|
||||
assertSafeOffset(value: number, label?: string): number;
|
||||
checkedOffsetAdd(offset: number, length: number, maximum?: number, label?: string): number;
|
||||
checkedByteRange(availableBytes: number, offset: number, length: number, label?: string): ByteRange;
|
||||
class ByteCursor { /* bounded typed reads, seek/skip and subcursors */ }
|
||||
ownedBytes(input: BytesLike, maximumBytes?: number): Uint8Array;
|
||||
```
|
||||
|
||||
`HelperLimitError` extends `RangeError` and exposes numeric `actual` and `limit`
|
||||
@@ -28,6 +35,10 @@ properties. Per-operation ceilings can be made narrower. They are compatibility
|
||||
and denial-of-service boundaries, not a substitute for an application-wide
|
||||
memory budget.
|
||||
|
||||
`ByteCursor` defaults to the shared 16 MiB input ceiling and never advances
|
||||
after a failed read. It is non-owning by default; `readBytes(length, true)`,
|
||||
`bytes(true)` and bounded `ownedBytes` make explicit retained copies.
|
||||
|
||||
## Encoding and URLs
|
||||
|
||||
```ts
|
||||
@@ -65,6 +76,18 @@ opens or fetches the result.
|
||||
|
||||
```ts
|
||||
type DigestAlgorithm = "SHA-1" | "SHA-256" | "SHA-384" | "SHA-512";
|
||||
type ChecksumAlgorithm = "CRC-32" | "Adler-32" | "FNV-1a-32";
|
||||
|
||||
interface IncrementalChecksum {
|
||||
readonly algorithm: ChecksumAlgorithm;
|
||||
readonly bytesProcessed: number;
|
||||
update(input: BytesLike): this;
|
||||
digest(): number;
|
||||
digestHex(): string;
|
||||
reset(): this;
|
||||
}
|
||||
|
||||
createIncrementalChecksum(algorithm: ChecksumAlgorithm, maximumBytes?: number): IncrementalChecksum;
|
||||
|
||||
crc32(input: BytesLike, maximumBytes?: number): number;
|
||||
adler32(input: BytesLike, maximumBytes?: number): number;
|
||||
@@ -88,6 +111,26 @@ Digests use Web Crypto. SHA-1 is available only for interoperability. Checksums
|
||||
and hashes do not establish authorship, and none of these functions is a
|
||||
password-hashing API.
|
||||
|
||||
## Byte sources
|
||||
|
||||
```ts
|
||||
type ByteSource = Blob | ReadableStream<BytesLike> | AsyncIterable<BytesLike>;
|
||||
interface ByteSourceProgress { processedBytes: number; totalBytes?: number }
|
||||
|
||||
iterateByteChunks(source: ByteSource, options?: ConsumeByteSourceOptions): AsyncGenerator<Uint8Array>;
|
||||
consumeByteSource(source: ByteSource, consume: (chunk: Uint8Array) => void | Promise<void>, options?: ConsumeByteSourceOptions): Promise<number>;
|
||||
checksumByteSource(source: ByteSource, checksum?: ChecksumAlgorithm | IncrementalChecksum, options?: ConsumeByteSourceOptions): Promise<number>;
|
||||
digestByteSource(source: ByteSource, algorithm?: DigestAlgorithm, options?: DigestByteSourceOptions): Promise<Uint8Array>;
|
||||
digestByteSourceHex(source: ByteSource, algorithm?: DigestAlgorithm, options?: DigestByteSourceOptions): Promise<string>;
|
||||
```
|
||||
|
||||
Every source is bounded and supports cancellation and progress. A supplied
|
||||
`knownTotalBytes` is an exact contract rather than an unchecked progress hint.
|
||||
CRC-32,
|
||||
Adler-32 and FNV-1a are genuinely incremental and constant-memory. Web Crypto
|
||||
does not expose incremental SHA state, so `digestByteSource` retains chunks up
|
||||
to the caller's explicit ceiling before invoking its one-shot digest API.
|
||||
|
||||
## Network
|
||||
|
||||
```ts
|
||||
@@ -140,6 +183,9 @@ createObjectUrlLease(
|
||||
blob: Blob,
|
||||
urlApi?: Pick<typeof URL, "createObjectURL" | "revokeObjectURL">,
|
||||
): ObjectUrlLease;
|
||||
createObjectUrlLeasePool<TKey = string>(urlApi?: UrlApi): ObjectUrlLeasePool<TKey>;
|
||||
planBlobDownloads(input: Iterable<BlobDownload>, options?: PlanBlobDownloadsOptions): readonly PlannedBlobDownload[];
|
||||
triggerBlobDownloads(input: Iterable<BlobDownload>, options?: TriggerBlobDownloadsOptions): TriggeredBlobDownloads;
|
||||
triggerBlobDownload(
|
||||
blob: Blob,
|
||||
filename: string,
|
||||
@@ -151,6 +197,44 @@ triggerBlobDownload(
|
||||
object URL revocation for the next task. Long-lived previews should instead
|
||||
keep a lease and call `revoke()` when replaced or unmounted.
|
||||
|
||||
Batch planning consumes at most the configured item ceiling, preserves input
|
||||
order by default, sanitizes every name and adds
|
||||
stable ` (2)`, ` (3)` suffixes for case-insensitive collisions. All batch URLs
|
||||
are revocable as one group. Browsers may still ask users to permit multiple
|
||||
downloads.
|
||||
|
||||
## Worker jobs
|
||||
|
||||
```ts
|
||||
const WORKER_JOB_PROTOCOL = "add-ideas.worker-job/v1";
|
||||
|
||||
startWorkerJob<TPayload, TResult, TProgress, TError>(
|
||||
worker: WorkerJobEndpoint,
|
||||
payload: TPayload,
|
||||
options?: StartWorkerJobOptions<TProgress, TError>,
|
||||
): WorkerJobHandle<TResult>;
|
||||
|
||||
createWorkerJobMessageHandler<TPayload, TResult, TProgress, TError>(
|
||||
run: (payload: TPayload, context: WorkerJobContext<TProgress>) => TResult | Promise<TResult>,
|
||||
postMessage: (response: WorkerJobResponse<TResult, TProgress, TError>) => void,
|
||||
options: WorkerJobHandlerOptions<TError>,
|
||||
): (event: MessageEvent<WorkerJobCommand<TPayload>>) => void;
|
||||
```
|
||||
|
||||
The client filters responses by protocol and job ID, forwards progress,
|
||||
propagates abort reasons, enforces a hard timeout by terminating disposable
|
||||
workers and removes all listeners when settled. Worker handlers expose the
|
||||
same deadline and cancellation signal for cooperative asynchronous work.
|
||||
|
||||
## Display
|
||||
|
||||
```ts
|
||||
formatBytes(bytes: number, options?: FormatBytesOptions): string;
|
||||
```
|
||||
|
||||
Formatting is deterministic and defaults to IEC units. It supports SI units,
|
||||
fixed precision, signed quantities and an explicit invalid-value label.
|
||||
|
||||
## Remaining groups
|
||||
|
||||
| Group | Exports |
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
const CACHE_PREFIX = "helper-tools-shell-";
|
||||
const CACHE_NAME = `${CACHE_PREFIX}0.1.0`;
|
||||
const CACHE_NAME = `${CACHE_PREFIX}0.2.0`;
|
||||
const CORE = ["./", "./manifest.webmanifest", "./favicon.svg"];
|
||||
|
||||
self.addEventListener("install", (event) => {
|
||||
|
||||
+14
-1
@@ -3,7 +3,7 @@
|
||||
"schemaVersion": 1,
|
||||
"id": "de.add-ideas.helper-tools",
|
||||
"name": "Helper Tools",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"description": "Encode, convert, inspect and calculate locally.",
|
||||
"entry": "./",
|
||||
"icon": "./favicon.svg",
|
||||
@@ -32,6 +32,19 @@
|
||||
"crossOriginIsolated": false,
|
||||
"topLevelContext": false
|
||||
},
|
||||
"io": {
|
||||
"accepts": [
|
||||
{ "mediaType": "text/plain", "extensions": [".txt"] },
|
||||
{ "mediaType": "application/json", "extensions": [".json"] },
|
||||
{ "mediaType": "text/csv", "extensions": [".csv"] }
|
||||
],
|
||||
"produces": [
|
||||
{ "mediaType": "text/plain", "extensions": [".txt"] },
|
||||
{ "mediaType": "application/json", "extensions": [".json"] },
|
||||
{ "mediaType": "text/csv", "extensions": [".csv"] }
|
||||
]
|
||||
},
|
||||
"capabilities": { "required": [], "optional": ["web-crypto", "workers"] },
|
||||
"privacy": {
|
||||
"processing": "local",
|
||||
"fileUploads": false,
|
||||
|
||||
Reference in New Issue
Block a user