adaptive-extender 0.11.1 → 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -10
- package/README.md +37 -32
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,13 +1,23 @@
|
|
|
1
|
-
## 0.11.
|
|
2
|
-
- Added `
|
|
3
|
-
- Added `
|
|
4
|
-
- Added `
|
|
5
|
-
- Added `
|
|
6
|
-
- Added `
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
- `
|
|
1
|
+
## 0.11.2 (21.06.2026)
|
|
2
|
+
- Added `Number.prototype.snap(step)` — snaps a number to the nearest multiple of `step`.
|
|
3
|
+
- Added `Array.Of(type)` portable adapter for typed arrays, as a `PortableConstructor` wrapper usable with `@Field`.
|
|
4
|
+
- Added `Set.Of(type)` portable adapter for typed sets, serialized as arrays.
|
|
5
|
+
- Added `Map.AsRecord(type)` portable adapter — converts `Map<string, T>` to and from a plain `Record<string, S>`.
|
|
6
|
+
- Added `Map.AsTuples(typeKey, typeValue)` portable adapter — converts `Map<K, V>` to and from `[K, V][]` tuple arrays.
|
|
7
|
+
- Added `Date.AsTimestamp` portable adapter — converts between `Date` instances and millisecond timestamps.
|
|
8
|
+
- Added `Date.AsUnixSeconds` portable adapter — converts between `Date` instances and Unix-second integers.
|
|
9
|
+
- Added `Optional.Of(type)` and `Optional.map(value, fn)` static methods on the `Optional` class.
|
|
10
|
+
- Added `Nullable.Of(type)` and `Nullable.map(value, fn)` static methods on the `Nullable` class.
|
|
11
|
+
- Added `Enum.Of(reference)` static method on the new `Enum` class.
|
|
12
|
+
- Added `Storage.openCell(key, initial)`, `Storage.openPortableCell(key, model, instance)`, and `Storage.openBufferedCell(key, model, instance)` factory methods on the `Storage` prototype.
|
|
13
|
+
- `BufferedCell.save()` returns `Promise<boolean>` — resolves `true` when persisted, `false` if cancelled (superseded or aborted); rejects only on serialization failure.
|
|
14
|
+
- **Breaking:** Renamed `Archive` → `Cell`, `ArchiveManager` → `PortableCell`, `ArchiveRepository` → `BufferedCell`. All three constructors now require an explicit `storage` as their first argument (e.g. `localStorage.openBufferedCell(key, model, instance)`) — the backend is no longer hardcoded to `localStorage`.
|
|
15
|
+
- **Breaking:** `Optional(type)` and `Nullable(type)` call syntax removed — use `Optional.Of(type)` and `Nullable.Of(type)` instead.
|
|
16
|
+
- **Breaking:** `ArrayOf(type)`, `SetOf(type)`, `RecordOf(type)`, `MapOf(K, V)` adapter functions removed — use `Array.Of(type)`, `Set.Of(type)`, `Map.AsRecord(type)`, `Map.AsTuples(K, V)` instead.
|
|
17
|
+
- **Breaking:** `EnumAs(reference)` function removed — use `Enum.Of(reference)` instead.
|
|
18
|
+
- **Breaking:** `Timestamp` and `UnixSeconds` portable constants removed — use `Date.AsTimestamp` and `Date.AsUnixSeconds` instead.
|
|
19
|
+
- **Breaking:** Removed `Reflect.mapNull`, `Reflect.mapUndefined`, and `Reflect.mapNullable` — use `Nullable.map(value, fn)` and `Optional.map(value, fn)` instead.
|
|
20
|
+
- **Breaking:** `@Field(type, "name")` positional string shorthand removed — use `@Field(type, { name: "name" })` options object instead.
|
|
11
21
|
|
|
12
22
|
## 0.10.5 (13.06.2026)
|
|
13
23
|
- Bugfix at [portable](./src/core/portable.ts).
|
package/README.md
CHANGED
|
@@ -47,6 +47,9 @@ const pixelX = angle.lerp(0, 360, 0, canvasWidth);
|
|
|
47
47
|
// True mathematical modulo — works correctly with negative numbers
|
|
48
48
|
const wrappedIndex = (-1).mod(items.length); // → items.length - 1
|
|
49
49
|
|
|
50
|
+
// Snap to a grid step
|
|
51
|
+
const snapped = (3.7).snap(0.5); // → 4
|
|
52
|
+
|
|
50
53
|
// Chainable fallback for invalid values
|
|
51
54
|
const ratio = (numerator / denominator).insteadNaN(0).insteadInfinity(1);
|
|
52
55
|
```
|
|
@@ -268,7 +271,7 @@ class AppConfig extends Model {
|
|
|
268
271
|
@Field(Number)
|
|
269
272
|
DB_PORT: number = 5432;
|
|
270
273
|
|
|
271
|
-
@Field(Optional(String))
|
|
274
|
+
@Field(Optional.Of(String))
|
|
272
275
|
LOG_LEVEL?: string;
|
|
273
276
|
}
|
|
274
277
|
|
|
@@ -284,7 +287,7 @@ Binds classes to their schema via decorators. Importing from JSON validates type
|
|
|
284
287
|
### Basic Usage
|
|
285
288
|
|
|
286
289
|
```typescript
|
|
287
|
-
import { Model, Field,
|
|
290
|
+
import { Model, Field, Optional, Nullable } from "adaptive-extender/core";
|
|
288
291
|
|
|
289
292
|
class Tag extends Model {
|
|
290
293
|
@Field(String)
|
|
@@ -298,13 +301,13 @@ class Article extends Model {
|
|
|
298
301
|
@Field(Number)
|
|
299
302
|
views: number = 0;
|
|
300
303
|
|
|
301
|
-
@Field(
|
|
304
|
+
@Field(Array.Of(Tag))
|
|
302
305
|
tags: Tag[] = [];
|
|
303
306
|
|
|
304
|
-
@Field(Optional(String))
|
|
307
|
+
@Field(Optional.Of(String))
|
|
305
308
|
subtitle?: string;
|
|
306
309
|
|
|
307
|
-
@Field(Nullable(String))
|
|
310
|
+
@Field(Nullable.Of(String))
|
|
308
311
|
draft: string | null = null;
|
|
309
312
|
}
|
|
310
313
|
|
|
@@ -343,16 +346,18 @@ const animal = Animal.import(json, "api.animal");
|
|
|
343
346
|
|
|
344
347
|
### Adapters
|
|
345
348
|
|
|
346
|
-
| Adapter
|
|
347
|
-
|
|
|
348
|
-
| `
|
|
349
|
-
| `
|
|
350
|
-
| `
|
|
351
|
-
| `
|
|
352
|
-
| `Optional(T)`
|
|
353
|
-
| `Nullable(T)`
|
|
354
|
-
| `Deferred(_ => T)`
|
|
355
|
-
| `
|
|
349
|
+
| Adapter | Type |
|
|
350
|
+
| :------------------- | :------------------------------------- |
|
|
351
|
+
| `Array.Of(T)` | `T[]` |
|
|
352
|
+
| `Set.Of(T)` | `Set<T>` ↔ `T[]` |
|
|
353
|
+
| `Map.AsRecord(T)` | `Map<string, T>` ↔ `Record<string, T>` |
|
|
354
|
+
| `Map.AsTuples(K, V)` | `Map<K, V>` ↔ `[K, V][]` |
|
|
355
|
+
| `Optional.Of(T)` | `T \| undefined` |
|
|
356
|
+
| `Nullable.Of(T)` | `T \| null` |
|
|
357
|
+
| `Deferred(_ => T)` | Circular references |
|
|
358
|
+
| `Enum.Of(E)` | TypeScript `enum` or const-object enum |
|
|
359
|
+
| `Date.AsTimestamp` | `Date` ↔ milliseconds (`number`) |
|
|
360
|
+
| `Date.AsUnixSeconds` | `Date` ↔ Unix seconds (`number`) |
|
|
356
361
|
|
|
357
362
|
## Web
|
|
358
363
|
|
|
@@ -392,12 +397,12 @@ const fixedEngine = new StaticEngine({ launch: true });
|
|
|
392
397
|
fixedEngine.limit = 30;
|
|
393
398
|
```
|
|
394
399
|
|
|
395
|
-
###
|
|
400
|
+
### Storage (localStorage)
|
|
396
401
|
|
|
397
|
-
Type-safe
|
|
402
|
+
Type-safe storage with buffered access and auto-save. Use the factory methods on any `Storage` instance (`localStorage`, `sessionStorage`, or custom) to create typed cells.
|
|
398
403
|
|
|
399
404
|
```typescript
|
|
400
|
-
import {
|
|
405
|
+
import { Model, Field } from "adaptive-extender/web";
|
|
401
406
|
|
|
402
407
|
class Settings extends Model {
|
|
403
408
|
@Field(Boolean)
|
|
@@ -407,16 +412,25 @@ class Settings extends Model {
|
|
|
407
412
|
volume: number = 1;
|
|
408
413
|
}
|
|
409
414
|
|
|
410
|
-
|
|
415
|
+
// BufferedCell — buffered read/write with debounced auto-save
|
|
416
|
+
const cell = localStorage.openBufferedCell("settings", Settings, new Settings());
|
|
411
417
|
|
|
412
|
-
const settings =
|
|
418
|
+
const settings = cell.content;
|
|
413
419
|
settings.volume = 0.5;
|
|
414
420
|
|
|
415
421
|
// save() resolves true when persisted, false if cancelled (superseded or aborted), rejects only on serialization failure
|
|
416
|
-
const saved = await
|
|
417
|
-
await
|
|
422
|
+
const saved = await cell.save(); // save immediately
|
|
423
|
+
await cell.save(3000); // debounced — save after 3 seconds
|
|
418
424
|
// A pending save resolves false when superseded by a new call or cancelled by abort()
|
|
419
|
-
|
|
425
|
+
cell.reset(); // abort pending save and revert to initial state
|
|
426
|
+
|
|
427
|
+
// PortableCell — direct typed read/write without buffering
|
|
428
|
+
const typed = localStorage.openPortableCell("config", Settings, new Settings());
|
|
429
|
+
typed.content = settings;
|
|
430
|
+
|
|
431
|
+
// Cell — raw JSON storage
|
|
432
|
+
const raw = localStorage.openCell("flags", { debug: false });
|
|
433
|
+
raw.data = { debug: true };
|
|
420
434
|
```
|
|
421
435
|
|
|
422
436
|
### Promise Utilities
|
|
@@ -431,15 +445,6 @@ const result = await Promise.withSignal((signal, resolve, reject) => {
|
|
|
431
445
|
});
|
|
432
446
|
```
|
|
433
447
|
|
|
434
|
-
## Reflect Utilities
|
|
435
|
-
|
|
436
|
-
```typescript
|
|
437
|
-
// Apply a function only if the value is not null / undefined
|
|
438
|
-
const upper = Reflect.mapNull(maybeNull, text => text.toUpperCase());
|
|
439
|
-
const trimmed = Reflect.mapUndefined(maybeUndefined, text => text.trim());
|
|
440
|
-
const parsed = Reflect.mapNullable(maybeNullable, text => Number.parseInt(text));
|
|
441
|
-
```
|
|
442
|
-
|
|
443
448
|
## License
|
|
444
449
|
|
|
445
450
|
Apache-2.0
|