@vicin/sigil 3.0.0 → 3.1.1
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 +17 -0
- package/README.md +66 -12
- package/dist/index.d.mts +120 -196
- package/dist/index.d.ts +120 -196
- package/dist/index.global.js +530 -4
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +526 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +515 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [3.1.1] - 2026-02-25
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Updated README.md
|
|
10
|
+
|
|
11
|
+
## [3.1.0] - 2026-02-25
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `isExactType` is added to check for exact instances (children are ingored as well)
|
|
16
|
+
|
|
17
|
+
### Removed
|
|
18
|
+
|
|
19
|
+
- `SigilOptions.skipLabelInheritanceCheck` is removed.
|
|
20
|
+
- `isOfTypeStrict` is removed.
|
|
21
|
+
|
|
5
22
|
## [3.0.0] - 2026-02-24
|
|
6
23
|
|
|
7
24
|
### Added
|
package/README.md
CHANGED
|
@@ -16,16 +16,14 @@
|
|
|
16
16
|
## Important Notes Before Using
|
|
17
17
|
|
|
18
18
|
- **Explicit class identity:** `Sigil` uses passed class label to identify classes, which means that the developer is responsible for uniqueness of classes by passing unique labels.
|
|
19
|
-
- **Performance:** Minimal overhead, `.isOfType()` is slightly slower than native `instanceof`. Avoid in ultra-hot paths.
|
|
20
19
|
- **Simple instanceof Fix:** If you just need runtime checks without extras, see the [minimal mode](#minimal-mode).
|
|
21
20
|
|
|
22
21
|
## Features
|
|
23
22
|
|
|
24
|
-
- ✅ **Drop-in `instanceof` replacement** that works across bundles, HMR, and monorepos
|
|
23
|
+
- ✅ **Drop-in `instanceof` replacement** that works across bundles, HMR, and monorepos, Also can check for **exact class instance**
|
|
25
24
|
- ✅ **True nominal typing** with zero runtime cost
|
|
26
|
-
- ✅ **
|
|
27
|
-
- ✅
|
|
28
|
-
- ✅ Full TypeScript 5.0+ support + excellent JSDoc
|
|
25
|
+
- ✅ **Tiny less than 1.5 KB minified and brotlied** measured using size-limit
|
|
26
|
+
- ✅ **Performant as native instanceof** but with guaranteed checks
|
|
29
27
|
|
|
30
28
|
---
|
|
31
29
|
|
|
@@ -46,6 +44,7 @@
|
|
|
46
44
|
- [Options & configuration](#options--configuration)
|
|
47
45
|
- [Minimal mode](#minimal-mode)
|
|
48
46
|
- [Strict mode](#strict-mode)
|
|
47
|
+
- [Benchmarks](#benchmarks)
|
|
49
48
|
- [Contributing](#contributing)
|
|
50
49
|
- [License](#license)
|
|
51
50
|
- [Author](#author)
|
|
@@ -151,7 +150,7 @@ Congratulations — you’ve opted into `Sigil` and you can start replacing `ins
|
|
|
151
150
|
|
|
152
151
|
### Terminology
|
|
153
152
|
|
|
154
|
-
- **Label**: An identity (string) such as `@scope/pkg.ClassName`, but can be random string (e.g. `@Sigil
|
|
153
|
+
- **Label**: An identity (string) such as `@scope/pkg.ClassName`, but can be random string (e.g. `@Sigil-auto:ClassName:mm2gkdwn:0:g1sq`) if no label passed.
|
|
155
154
|
- **EffectiveLabel:** A human-readable (string) such as `@scope/pkg.ClassName`, if no label is passed it inherit the last defined label.
|
|
156
155
|
- **Label lineage**: Array of labels for ancestry.
|
|
157
156
|
- **Label set**: Set of labels for fast checks.
|
|
@@ -171,6 +170,7 @@ if (obj instanceof User) { ... }
|
|
|
171
170
|
|
|
172
171
|
// With Sigil
|
|
173
172
|
if (User.isOfType(obj)) { ... } // This still works even if User was bundled twice.
|
|
173
|
+
if (User.isExactType(obj)) { ... } // Or check for exactly same constructor not its children
|
|
174
174
|
```
|
|
175
175
|
|
|
176
176
|
- **Manual Branding Overhead:** Custom identifiers lead to boilerplate and maintenance issues, `Sigil` add reliable inheritance-aware nominal branding with just one line of code.
|
|
@@ -235,9 +235,17 @@ class Admin extends User {
|
|
|
235
235
|
const admin = new Admin();
|
|
236
236
|
const user = new User();
|
|
237
237
|
|
|
238
|
+
// Instanceof like behavior
|
|
238
239
|
console.log(Admin.isOfType(admin)); // true
|
|
239
240
|
console.log(Admin.isOfType(user)); // false
|
|
240
241
|
console.log(User.isOfType(admin)); // true
|
|
242
|
+
console.log(User.isOfType(user)); // true
|
|
243
|
+
|
|
244
|
+
// Exact checks
|
|
245
|
+
console.log(Admin.isOfType(admin)); // true
|
|
246
|
+
console.log(Admin.isOfType(user)); // false
|
|
247
|
+
console.log(User.isOfType(user)); // true
|
|
248
|
+
console.log(User.isOfType(admin)); // false (Admin is child indeed but this checks for user specifically)
|
|
241
249
|
|
|
242
250
|
type test1 = Admin extends User ? true : false; // true
|
|
243
251
|
type test2 = User extends Admin ? true : false; // false
|
|
@@ -301,11 +309,11 @@ When a constructor is decorated/sigilified it will expose the following **static
|
|
|
301
309
|
|
|
302
310
|
- `SigilLabel` — the identity label string.
|
|
303
311
|
- `SigilEffectiveLabel` — the human label string.
|
|
304
|
-
- `SigilLabelLineage` — readonly array of labels representing parent → child.
|
|
305
|
-
- `SigilLabelSet` — readonly `Set<string>` for
|
|
312
|
+
- `SigilLabelLineage` — readonly array of labels representing parent → child for debugging.
|
|
313
|
+
- `SigilLabelSet` — readonly `Set<string>` for debugging.
|
|
306
314
|
- `isSigilified(obj)` — runtime predicate that delegates to `isSigilInstance`.
|
|
307
|
-
- `isOfType(other)` —
|
|
308
|
-
- `
|
|
315
|
+
- `isOfType(other)` — check if other is an instance of this constructor or its children.
|
|
316
|
+
- `isExactType(other) `— check if other is an instance exactly this constructor.
|
|
309
317
|
|
|
310
318
|
Instances of sigilified classes expose instance helpers:
|
|
311
319
|
|
|
@@ -313,8 +321,8 @@ Instances of sigilified classes expose instance helpers:
|
|
|
313
321
|
- `getSigilEffectiveLabel()` — returns the human label.
|
|
314
322
|
- `getSigilLabelLineage()` — returns lineage array.
|
|
315
323
|
- `getSigilLabelSet()` — returns readonly Set.
|
|
316
|
-
- `isOfType(other)` —
|
|
317
|
-
- `
|
|
324
|
+
- `isOfType(other)` — check if other is an instance of the same class or its children as this.
|
|
325
|
+
- `isExactType(other) `— check if other is an instance exactly the same constructor.
|
|
318
326
|
|
|
319
327
|
---
|
|
320
328
|
|
|
@@ -363,6 +371,52 @@ Now if you forgot to pass a label error is thrown.
|
|
|
363
371
|
|
|
364
372
|
---
|
|
365
373
|
|
|
374
|
+
## Benchmarks
|
|
375
|
+
|
|
376
|
+
Sigil is built for **real-world performance**. Below are the latest micro-benchmark results (run on **Node.js v20.12.0**).
|
|
377
|
+
To run benchmarks on your machine fetch source code from [github](https://github.com/ZiadTaha62/sigil) and run `npm run bench` in your console.
|
|
378
|
+
|
|
379
|
+
### 1. Runtime Type Checking
|
|
380
|
+
|
|
381
|
+
| Depth | `instanceof` (per op) | `isOfType` (ctor) | `isOfType` (instance) | `isExactType` (ctor) | `isExactType` (instance) |
|
|
382
|
+
| ----- | --------------------- | ----------------- | --------------------- | -------------------- | ------------------------ |
|
|
383
|
+
| 0 | 0.000010 ms | 0.000025 ms | **0.000010 ms** | 0.000027 ms | 0.000012 ms |
|
|
384
|
+
| 3 | 0.000032 ms | 0.000045 ms | **0.000027 ms** | 0.000038 ms | **0.000025 ms** |
|
|
385
|
+
| 5 | 0.000034 ms | 0.000046 ms | **0.000028 ms** | 0.000037 ms | **0.000026 ms** |
|
|
386
|
+
| 10 | 0.000044 ms | 0.000045 ms | **0.000029 ms** | 0.000038 ms | **0.000027 ms** |
|
|
387
|
+
| 15 | 0.000058 ms | 0.000063 ms | **0.000051 ms** | 0.000069 ms | **0.000053 ms** |
|
|
388
|
+
|
|
389
|
+
> **Key takeaway**:
|
|
390
|
+
> `isOfType` has **practically the same performance as native `instanceof`**, slightly **slower** on static calls and slightly **faster** on the instance side.
|
|
391
|
+
> `isExactType` adds only a tiny negligible cost and remains extremely fast even on deep hierarchies.
|
|
392
|
+
|
|
393
|
+
### 2. Class Definition & Instance Creation
|
|
394
|
+
|
|
395
|
+
| Scenario | Definition (per class) | Instantiation (per instance) |
|
|
396
|
+
| ------------------------------- | ---------------------- | ---------------------------- |
|
|
397
|
+
| Empty plain class | 0.0122 ms | 0.00019 ms |
|
|
398
|
+
| Empty Sigil class | 0.0672 ms | 0.00059 ms |
|
|
399
|
+
| Small (5 props + 3 methods) | 0.0172 ms | 0.00327 ms |
|
|
400
|
+
| Large (15 props + 10 methods) | 0.0212 ms | 0.00922 ms |
|
|
401
|
+
| Large Sigil | 0.0780 ms | 0.01177 ms |
|
|
402
|
+
| Extended chain depth 5 – plain | 0.0897 ms | 0.01809 ms |
|
|
403
|
+
| Extended chain depth 5 – Sigil | 0.3978 ms | 0.02020 ms |
|
|
404
|
+
| Extended chain depth 10 – plain | 0.2042 ms | 0.05759 ms |
|
|
405
|
+
| Extended chain depth 10 – Sigil | 0.8127 ms | 0.06675 ms |
|
|
406
|
+
|
|
407
|
+
> **Key takeaways**:
|
|
408
|
+
>
|
|
409
|
+
> - Class definition is a **one-time cost** at module load time. Even at depth 10 the cost stays well under 1 ms per class.
|
|
410
|
+
> - Instance creation adds a small fixed overhead of ~0.4–0.6 µs per object, which becomes completely negligible as your classes grow in size and complexity.
|
|
411
|
+
|
|
412
|
+
### Bundle Size
|
|
413
|
+
|
|
414
|
+
**less than 1.5 KB** (minified + Brotli, including all dependencies)
|
|
415
|
+
|
|
416
|
+
This makes Sigil one of the smallest full-featured solutions for nominal typing + reliable runtime identity.
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
366
420
|
## Contributing
|
|
367
421
|
|
|
368
422
|
Any contributions you make are **greatly appreciated**.
|