@vicin/sigil 1.0.0 → 1.0.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.
Files changed (3) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +57 -24
  3. package/package.json +6 -1
package/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) GitHub, Inc. and contributors
1
+ Copyright (c) 2026 Ziad Taha and contributors
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
4
 
package/README.md CHANGED
@@ -11,9 +11,9 @@
11
11
 
12
12
  **Note: You should read these parts before implementing `Sigil` in you code:**
13
13
 
14
- - **Security note:** `Sigil` exposes a global registry of all sigilized classes, this means that all sigilized classes can be accessed anywhere in the code. so **avoid** siglizing security sensitive classes or any class that you want to make it unaccessable outside it's module. read more [Registery](#registry).
14
+ - **Security note:** `Sigil` stores constructor references in the global registry. While it doesn't expose private instance data, it does mean any module can get constructor of the class. so **avoid** siglizing classes you want to make it unaccessable outside it's module. read more [Registery](#registry).
15
15
 
16
- - **Performance note:** `Sigil` attaches couple methods to every sigilized class instance, this is negligible in almost all cases, also `.isOfType()` although being reliable and performance optimized but it still marginally less performant that native `instanceof` checks, so if you want maximum performance in cases like hot-path code it is not advised to use `Sigil` as it's built for consistency and maintainability mainly at the cost of minimal performance overhead.
16
+ - **Performance note:** `Sigil` attaches couple methods to every sigilized class instance, this is negligible in almost all cases, also `.isOfType()` although being reliable and performance optimized but it still less performant that native `instanceof` checks, so if you want maximum performance in cases like hot-path code it is not advised to use `Sigil` as it's built for consistency and maintainability mainly at the cost of minimal performance overhead.
17
17
 
18
18
  ---
19
19
 
@@ -35,16 +35,24 @@
35
35
  - [Troubleshooting & FAQ](#troubleshooting--faq)
36
36
  - [Best practices](#best-practices)
37
37
  - [Phantom](#phantom)
38
+ - [Contributing](#contributing)
39
+ - [License](#license)
40
+ - [Author](#author)
38
41
 
39
42
  ---
40
43
 
41
44
  ## Features
42
45
 
43
46
  - Attach **stable runtime identity** to classes using `Symbol.for(label)`.
47
+
44
48
  - **Type-level branding** so distinct domain identities are enforced by TypeScript.
49
+
45
50
  - **Lineage tracking** (arrays + sets of symbols) for O(1) and O(n) checks.
51
+
46
52
  - Easy to use: decorator (`@WithSigil`), mixin (`Sigilify`), and HOF (Higher order function) helpers (`withSigil`, `withSigilTyped`, `typed`).
53
+
47
54
  - **Global registry** to centralize classes (query any class by it's label in run-time) and guard against duplicate labels.
55
+
48
56
  - Minimal runtime overhead in production (DEV checks can be toggled off).
49
57
 
50
58
  ---
@@ -54,11 +62,11 @@
54
62
  ### Install
55
63
 
56
64
  ```bash
57
- npm install sigil
65
+ npm install @vicin/sigil
58
66
  # or
59
- yarn add sigil
67
+ yarn add @vicin/sigil
60
68
  # or
61
- pnpm add sigil
69
+ pnpm add @vicin/sigil
62
70
  ```
63
71
 
64
72
  **Requirements**: TypeScript 5.0+ (for stage-3 decorators) and Node.js 18+ recommended.
@@ -68,7 +76,7 @@ pnpm add sigil
68
76
  Use the `Sigil` base class or the `Sigilify` mixin to opt a class into the Sigil runtime contract.
69
77
 
70
78
  ```ts
71
- import { Sigil, Sigilify } from 'sigil';
79
+ import { Sigil, Sigilify } from '@vicin/sigil';
72
80
 
73
81
  // Using the pre-sigilified base class:
74
82
  class User extends Sigil {}
@@ -84,7 +92,7 @@ This adds runtime metadata to the constructor and allows you to use runtime help
84
92
  Apply a label with the `@WithSigil` decorator. This is handy for small classes or when you prefer decorator syntax.
85
93
 
86
94
  ```ts
87
- import { Sigil, WithSigil } from 'sigil';
95
+ import { Sigil, WithSigil } from '@vicin/sigil';
88
96
 
89
97
  @WithSigil('@myorg/mypkg.User')
90
98
  class User extends Sigil {}
@@ -97,7 +105,7 @@ class User extends Sigil {}
97
105
  HOFs work well in many build setups and are idempotent-safe for HMR flows.
98
106
 
99
107
  ```ts
100
- import { Sigil, withSigil } from 'sigil';
108
+ import { Sigil, withSigil } from '@vicin/sigil';
101
109
 
102
110
  class _User extends Sigil {}
103
111
  const User = withSigil(_User, '@myorg/mypkg.User');
@@ -111,7 +119,7 @@ console.log(User.SigilLabel); // "@myorg/mypkg.User"
111
119
  If you want TypeScript to treat identities nominally (so `UserId` !== `PostId` despite identical shape), use the typed helpers.
112
120
 
113
121
  ```ts
114
- import { Sigil, withSigilTyped, GetInstance } from 'sigil';
122
+ import { Sigil, withSigilTyped, GetInstance } from '@vicin/sigil';
115
123
 
116
124
  class _User extends Sigil {}
117
125
  const User = withSigilTyped(_User, '@myorg/mypkg.User');
@@ -128,14 +136,14 @@ Migration old code into `Sigil` can be done seamlessly with this set-up:
128
136
  1. Set `SigilOptions.autofillLabels` to `true` at the start of the app so no errors are thrown in the migration stage:
129
137
 
130
138
  ```ts
131
- import { updateOptions } from 'sigil';
139
+ import { updateOptions } from '@vicin/sigil';
132
140
  updateOptions({ autofillLabels: true });
133
141
  ```
134
142
 
135
143
  2. Make you base classes extends `Sigil`:
136
144
 
137
145
  ```ts
138
- import { Sigil } from 'sigil';
146
+ import { Sigil } from '@vicin/sigil';
139
147
 
140
148
  class MyBaseClass {} // original
141
149
 
@@ -215,7 +223,7 @@ Basic patterns:
215
223
  Mixin / factory:
216
224
 
217
225
  ```ts
218
- import { Sigilify } from 'sigil';
226
+ import { Sigilify } from '@vicin/sigil';
219
227
 
220
228
  const MyClass = Sigilify(class {}, 'MyClass');
221
229
  ```
@@ -223,7 +231,7 @@ const MyClass = Sigilify(class {}, 'MyClass');
223
231
  Direct base-class extend:
224
232
 
225
233
  ```ts
226
- import { Sigil, WithSigil } from 'sigil';
234
+ import { Sigil, WithSigil } from '@vicin/sigil';
227
235
 
228
236
  class MyClass extends Sigil {}
229
237
  ```
@@ -234,7 +242,7 @@ Once you opt into the runtime contract, Sigil enforces consistency: in DEV mode,
234
242
  Decorator style:
235
243
 
236
244
  ```ts
237
- import { Sigil, WithSigil } from 'sigil';
245
+ import { Sigil, WithSigil } from '@vicin/sigil';
238
246
 
239
247
  @WithSigil('MyClass') // <-- Note `@WithSigil` used here cause it extended alreay sigilized class (Sigil). Error is thrown without it.
240
248
  class MyClass extends Sigil {}
@@ -243,7 +251,7 @@ class MyClass extends Sigil {}
243
251
  HOF (preferred for many workflows):
244
252
 
245
253
  ```ts
246
- import { Sigil, withSigil } from 'sigil';
254
+ import { Sigil, withSigil } from '@vicin/sigil';
247
255
 
248
256
  class _MyClass extends Sigil {}
249
257
  const MyClass = withSigil(_MyClass, 'MyClass');
@@ -262,7 +270,7 @@ Runtime metadata alone does not change TypeScript types. To get compile-time nom
262
270
  Example using a typed HOF:
263
271
 
264
272
  ```ts
265
- import { Sigil, withSigilTyped, GetInstance } from 'sigil';
273
+ import { Sigil, withSigilTyped, GetInstance } from '@vicin/sigil';
266
274
 
267
275
  // Untyped (runtime) base you extend as normal TS class code:
268
276
  class _User extends Sigil {}
@@ -291,7 +299,7 @@ This separation is necessary as typescript decorators doesn't affect type system
291
299
  Example of appraoch for class chain:
292
300
 
293
301
  ```ts
294
- import { Sigil, withSigilTyped, GetInstance } from 'sigil';
302
+ import { Sigil, withSigilTyped, GetInstance } from '@vicin/sigil';
295
303
 
296
304
  // Untyped base classes used for implementation:
297
305
  class _User extends Sigil {}
@@ -334,7 +342,7 @@ The update of Sigil brand types happens via HOF that are defined below actual cl
334
342
  Example:
335
343
 
336
344
  ```ts
337
- import { Sigil, withSigilTyped } from 'sigil';
345
+ import { Sigil, withSigilTyped } from '@vicin/sigil';
338
346
 
339
347
  class _X extends Sigil {
340
348
  // All logic for class
@@ -367,7 +375,7 @@ Earlier example used `InstanceType<>` to get instance of the class. It works wel
367
375
  So alternative in introduced which is `GetInstance`.
368
376
 
369
377
  ```ts
370
- import { Sigil, withSigilTyped, GetInstance } from 'sigil';
378
+ import { Sigil, withSigilTyped, GetInstance } from '@vicin/sigil';
371
379
 
372
380
  class _X extends Sigil {}
373
381
 
@@ -386,7 +394,7 @@ One of the downsides of defining typed class at the bottom is that we need to re
386
394
  Example of generic propagation:
387
395
 
388
396
  ```ts
389
- import { Sigil, withSigilTyped, GetInstance } from 'sigil';
397
+ import { Sigil, withSigilTyped, GetInstance } from '@vicin/sigil';
390
398
 
391
399
  // Untyped base classes used for implementation:
392
400
  class _X<G> extends Sigil {}
@@ -403,7 +411,7 @@ You may see error: `Property 'x' of exported anonymous class type may not be pri
403
411
  This comes from the fact that all typed classes are `anonymous class` as they are return of HOF and ts compiler struggle to type them safely. to avoid these error entirly all you need is exporting the untyped classes even if they are un-used as a good convention.
404
412
 
405
413
  ```ts
406
- import { Sigil, withSigilTyped, GetInstance } from 'sigil';
414
+ import { Sigil, withSigilTyped, GetInstance } from '@vicin/sigil';
407
415
 
408
416
  export class _X extends Sigil {} // <-- Just add 'export' here
409
417
 
@@ -487,7 +495,7 @@ Instances of sigilified classes expose instance helpers:
487
495
  Sigil exposes a small set of runtime options that control DEV behavior. These can be modified at app startup via `updateOptions(...)`.
488
496
 
489
497
  ```ts
490
- import { updateOptions } from 'sigil';
498
+ import { updateOptions } from '@vicin/sigil';
491
499
 
492
500
  updateOptions({
493
501
  autofillLabels: false, // auto-generate labels for subclasses that would otherwise inherit
@@ -531,7 +539,7 @@ Registry is stored in `globalThis` under `Symbol.for(__SIGIL_REGISTRY__)` so the
531
539
  Unfortunately concrete types of classes is not supported and all classes are stored as `ISigil` type. if you want concrete typings you can wrap registery:
532
540
 
533
541
  ```ts
534
- import { REGISTRY } from 'sigil';
542
+ import { REGISTRY } from '@vicin/sigil';
535
543
  import { MySigilClass1 } from './file1';
536
544
  import { MySigilClass2 } from './file2';
537
545
 
@@ -551,7 +559,7 @@ class MySigilRegistry {
551
559
  return REGISTRY.get(label) as any;
552
560
  }
553
561
  unregister(label: string): boolean {
554
- return REGISTRY.unregister();
562
+ return REGISTRY.unregister(label);
555
563
  }
556
564
  clear(): void {
557
565
  REGISTRY.clear();
@@ -618,3 +626,28 @@ A: You can set `SigilOptions.autofillLabels` to `true`. or if you more strict en
618
626
  `Phantom` is another lightweight TypeScript library I created for achieving **nominal typing** on primitives and objects through type-only metadata. It solves the problem of structural typing in TypeScript allowing accidental misuse of identical shapes (e.g., confusing `UserId` and `PostId` as both strings) by enabling compile-time distinctions with features like **brands**, **constrained identities**, **variants for states**, **additive traits**, and **reversible transformations**. This makes it ideal for domain-driven design (DDD) without runtime overhead.
619
627
 
620
628
  `Phantom` works seamlessly in conjunction with `Sigil`, use `Sigil` for nominal identity on classes (runtime-safe checks across bundles), and `Phantom` for primitives/objects. Together, they provide **end-to-end type safety**: e.g., a Sigil-branded `User` class could hold a Phantom-branded `UserId` string property, enforcing domain boundaries at both compile and runtime.
629
+
630
+ - **GitHub: [@phantom](https://github.com/ZiadTaha62/phantom)**
631
+ - **NPM: [@phantom](https://www.npmjs.com/package/@vicin/phantom)**
632
+
633
+ ---
634
+
635
+ ## Contributing
636
+
637
+ Any contributions you make are **greatly appreciated**.
638
+
639
+ Please see our [CONTRIBUTING.md](./CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
640
+
641
+ ## License
642
+
643
+ Distributed under the MIT License. See `LICENSE` for more information.
644
+
645
+ ---
646
+
647
+ ## Author
648
+
649
+ Built with ❤️ by **Ziad Taha**.
650
+
651
+ - **GitHub: [@ZiadTaha62](https://github.com/ZiadTaha62)**
652
+ - **NPM: [@ziadtaha62](https://www.npmjs.com/~ziadtaha62)**
653
+ - **Vicin: [@vicin](https://www.npmjs.com/org/vicin)**
package/package.json CHANGED
@@ -1,12 +1,17 @@
1
1
  {
2
2
  "name": "@vicin/sigil",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Lightweight TypeScript library for nominal identity classes",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/ZiadTaha62/sigil.git"
13
+ },
14
+ "homepage": "https://github.com/ZiadTaha62/sigil#readme",
10
15
  "scripts": {
11
16
  "build": "tsc",
12
17
  "lint": "eslint --fix",