@vicin/sigil 3.1.4 → 3.2.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 +121 -36
- package/dist/index.d.mts +19 -4
- package/dist/index.d.ts +19 -4
- package/dist/index.global.js +41 -21
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +41 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +40 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
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.2.1] - 2026-02-27
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Updated README.md
|
|
10
|
+
|
|
11
|
+
## [3.2.0] - 2026-02-27
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `RECOMMENDED_LABEL_REGEX` is the same as `DEFAULT_LABEL_REGEX` but renamed for clarity
|
|
16
|
+
- `getSigilLabels` to get registered sigil labels
|
|
17
|
+
|
|
18
|
+
### Deprecated
|
|
19
|
+
|
|
20
|
+
- `DEFAULT_LABEL_REGEX` is deprecated and will be removed in v4, use `RECOMMENDED_LABEL_REGEX` instead
|
|
21
|
+
|
|
5
22
|
## [3.1.4] - 2026-02-26
|
|
6
23
|
|
|
7
24
|
### Changed
|
package/README.md
CHANGED
|
@@ -7,23 +7,14 @@
|
|
|
7
7
|
|
|
8
8
|
`Sigil` gives you the power of **safe cross-bundle class instances checks** and **simple class nominal typing** if needed.
|
|
9
9
|
|
|
10
|
-
> **Key ideas:**
|
|
11
|
-
>
|
|
12
|
-
> - **Reliable Runtime Checks:** Uses `isOfType` instead of `instanceof` for cross-bundle reliability.
|
|
13
|
-
> - **Nominal Typing at Compile Time:** Distinguishes structurally similar types (e.g., UserId vs. PostId).
|
|
14
|
-
|
|
15
10
|
## Features
|
|
16
11
|
|
|
17
|
-
- ✅ **Drop-in `instanceof` replacement** that works across bundles
|
|
18
|
-
- ✅ **Simple nominal typing** with just one line of code for each class
|
|
19
|
-
- ✅ **Tiny less than 1.
|
|
12
|
+
- ✅ **Drop-in `instanceof` replacement** that works across bundles and monorepos, Also add check for **exact class instance**
|
|
13
|
+
- ✅ **Simple nominal typing** with just one line of code for each class (e.g., `UserId` vs. `PostId`)
|
|
14
|
+
- ✅ **Tiny less than 1.6 KB minified and brotlied** measured using [size-limit](https://www.npmjs.com/package/size-limit)
|
|
20
15
|
- ✅ **Performant as native instanceof** but with guaranteed checks
|
|
21
16
|
- ✅ **Test coverage is 100%** to ensure that runtime remains consistent and predictable
|
|
22
|
-
|
|
23
|
-
## Important Notes Before Using
|
|
24
|
-
|
|
25
|
-
- **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.
|
|
26
|
-
- **Simple instanceof Fix:** If you just need runtime checks without extras, see the [minimal mode](#minimal-mode).
|
|
17
|
+
- ✅ **Safe with strict rules to ensure uniqueness of labels**, if duplicate label is passed error is thrown immediately
|
|
27
18
|
|
|
28
19
|
---
|
|
29
20
|
|
|
@@ -39,7 +30,8 @@
|
|
|
39
30
|
- [Terminology](#terminology)
|
|
40
31
|
- [Purpose and Origins](#purpose-and-origins)
|
|
41
32
|
- [Implementation Mechanics](#implementation-mechanics)
|
|
42
|
-
- [
|
|
33
|
+
- [Example](#example)
|
|
34
|
+
- [Errors & throws](#errors--throws)
|
|
43
35
|
- [API reference](#api-reference)
|
|
44
36
|
- [Options & configuration](#options--configuration)
|
|
45
37
|
- [Minimal mode](#minimal-mode)
|
|
@@ -93,8 +85,6 @@ abstract class User extends Sigil {}
|
|
|
93
85
|
const MyClass = SigilifyAbstract(abstract class {}, '@myorg/mypkg.MyClass');
|
|
94
86
|
```
|
|
95
87
|
|
|
96
|
-
This adds runtime metadata to the constructor and allows you to use runtime helpers, see [API reference](#api-reference).
|
|
97
|
-
|
|
98
88
|
#### Extend `Sigil` classes
|
|
99
89
|
|
|
100
90
|
After opting into the `Sigil` contract, labels are passed to child classes to uniquely identify them, they can be supplied using two patterns:
|
|
@@ -119,9 +109,6 @@ import { Sigil, withSigil } from '@vicin/sigil';
|
|
|
119
109
|
|
|
120
110
|
class _User extends Sigil {}
|
|
121
111
|
const User = withSigil(_User, '@myorg/mypkg.User');
|
|
122
|
-
|
|
123
|
-
const user = new User();
|
|
124
|
-
console.log(User.SigilLabel); // "@myorg/mypkg.User"
|
|
125
112
|
```
|
|
126
113
|
|
|
127
114
|
### Migration
|
|
@@ -144,7 +131,7 @@ import { Sigil } from '@vicin/sigil';
|
|
|
144
131
|
class MyBaseClass extends Sigil {} // <-- add 'extends Sigil' here
|
|
145
132
|
```
|
|
146
133
|
|
|
147
|
-
Congratulations — you’ve opted into `Sigil` and you can start replacing `instanceof` with `isOfType`, however there is more to add to your system, check [Core concepts](#core-concepts) for more.
|
|
134
|
+
Congratulations — you’ve opted into `Sigil` and you can start replacing `instanceof` with `isOfType()` / `isExactType()`, however there is more to add to your system, check [Core concepts](#core-concepts) for more.
|
|
148
135
|
|
|
149
136
|
---
|
|
150
137
|
|
|
@@ -152,7 +139,7 @@ Congratulations — you’ve opted into `Sigil` and you can start replacing `ins
|
|
|
152
139
|
|
|
153
140
|
### Terminology
|
|
154
141
|
|
|
155
|
-
- **Label**: An identity (string) such as `@scope/pkg.ClassName`,
|
|
142
|
+
- **Label**: An identity (string) such as `@scope/pkg.ClassName`, must be unique for each `Sigil` class otherwise error is thrown.
|
|
156
143
|
- **EffectiveLabel:** A human-readable (string) such as `@scope/pkg.ClassName`, if no label is passed it inherit the last defined label.
|
|
157
144
|
- **isOfType**: Takes object argument and check if this object is an instance of calling class or it's children. Can be called from class instances as well.
|
|
158
145
|
- **isExactType**: Takes object argument and check if this object is an instance of calling class only. Can be called from class instances as well.
|
|
@@ -164,10 +151,10 @@ Congratulations — you’ve opted into `Sigil` and you can start replacing `ins
|
|
|
164
151
|
|
|
165
152
|
Sigil addresses issues in large monorepos and Domain-Driven Design (DDD):
|
|
166
153
|
|
|
167
|
-
- **Unreliable `instanceof`:** Bundling
|
|
154
|
+
- **Unreliable `instanceof`:** Bundling cause class redefinitions, breaking checks.
|
|
168
155
|
|
|
169
156
|
```ts
|
|
170
|
-
//
|
|
157
|
+
// Can be broken in monorepo
|
|
171
158
|
if (obj instanceof User) { ... }
|
|
172
159
|
|
|
173
160
|
// With Sigil
|
|
@@ -204,7 +191,7 @@ class MyClass extends Sigil {
|
|
|
204
191
|
}
|
|
205
192
|
```
|
|
206
193
|
|
|
207
|
-
You can avoid decorators and use HOF
|
|
194
|
+
You can avoid decorators and use HOF if needed:
|
|
208
195
|
|
|
209
196
|
```ts
|
|
210
197
|
import { Sigil, withSigil, sigil, ExtendSigil } from '@vicin/sigil';
|
|
@@ -219,7 +206,7 @@ type MyClass = InstanceType<typeof MyClass>;
|
|
|
219
206
|
|
|
220
207
|
Note that you can't use `InstanceType` on `private` or `protected` classes, however you can use `GetPrototype<T>` in such cases.
|
|
221
208
|
|
|
222
|
-
###
|
|
209
|
+
### Example
|
|
223
210
|
|
|
224
211
|
```ts
|
|
225
212
|
import { Sigil, WithSigil } from '@vicin/sigil';
|
|
@@ -244,13 +231,109 @@ console.log(User.isOfType(admin)); // true
|
|
|
244
231
|
console.log(User.isOfType(user)); // true
|
|
245
232
|
|
|
246
233
|
// Exact checks
|
|
247
|
-
console.log(Admin.
|
|
248
|
-
console.log(Admin.
|
|
249
|
-
console.log(User.
|
|
250
|
-
console.log(User.
|
|
251
|
-
|
|
234
|
+
console.log(Admin.isExactType(admin)); // true
|
|
235
|
+
console.log(Admin.isExactType(user)); // false
|
|
236
|
+
console.log(User.isExactType(user)); // true
|
|
237
|
+
console.log(User.isExactType(admin)); // false (Admin is child indeed but this checks for user specifically)
|
|
238
|
+
|
|
239
|
+
// Can use checks from instances
|
|
240
|
+
console.log(admin.isOfType(user)); // false
|
|
241
|
+
console.log(user.isOfType(admin)); // true
|
|
242
|
+
console.log(admin.isExactType(user)); // false
|
|
243
|
+
console.log(user.isExactType(admin)); // false
|
|
244
|
+
|
|
245
|
+
// Type checks are nominal
|
|
252
246
|
type test1 = Admin extends User ? true : false; // true
|
|
253
247
|
type test2 = User extends Admin ? true : false; // false
|
|
248
|
+
|
|
249
|
+
// Passed label must be unique (enforced by Sigil) so can be used as stable Id for class
|
|
250
|
+
// Also 'SigilLabelLineage' and 'SigilLabelSet' are useful for logging & debugging
|
|
251
|
+
console.log(Admin.SigilLabel); // '@myorg/Admin'
|
|
252
|
+
console.log(Admin.SigilEffectiveLabel); // '@myorg/Admin'
|
|
253
|
+
console.log(Admin.SigilLabelLineage); // ['Sigil', '@myorg/User', '@myorg/Admin']
|
|
254
|
+
console.log(Admin.SigilLabelSet); // Set(['Sigil', '@myorg/User', '@myorg/Admin'])
|
|
255
|
+
console.log(admin.getSigilLabel()); // '@myorg/Admin'
|
|
256
|
+
console.log(admin.getSigilEffectiveLabel()); // '@myorg/Admin'
|
|
257
|
+
console.log(admin.getSigilLabelLineage()); // ['Sigil', '@myorg/User', '@myorg/Admin']
|
|
258
|
+
console.log(admin.getSigilLabelSet()); // Set(['Sigil', '@myorg/User', '@myorg/Admin'])
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Errors & throws
|
|
262
|
+
|
|
263
|
+
Run-time errors that can be thrown by `Sigil`:
|
|
264
|
+
|
|
265
|
+
#### Double `Sigilify() / SigilifyAbstract()`
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
class A {}
|
|
269
|
+
const B = Sigilify(A, 'A');
|
|
270
|
+
const C = Sigilify(B, 'B'); // Throws: [Sigil Error] Class 'Sigilified' with label 'A' is already sigilified
|
|
271
|
+
|
|
272
|
+
abstract class AbsA {}
|
|
273
|
+
const AbsB = SigilifyAbstract(AbsA, 'AbsA');
|
|
274
|
+
const AbsC = SigilifyAbstract(AbsB, 'AbsB'); // Throws: [Sigil Error] Class 'Sigilified' with label 'AbsA' is already sigilified
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
#### `@WithSigil() / withSigil()` on non-Sigil class
|
|
278
|
+
|
|
279
|
+
```ts
|
|
280
|
+
@WithSigil('A')
|
|
281
|
+
class A {} // Throws: [Sigil Error] 'WithSigil' decorator accept only Sigil classes but used on class 'A'
|
|
282
|
+
|
|
283
|
+
withSigil(class A {}); // Throws: [Sigil Error] 'WithSigil' decorator accept only Sigil classes but used on class 'A'
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
#### Double `@WithSigil() / withSigil()`
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
@WithSigil('B')
|
|
290
|
+
@WithSigil('A')
|
|
291
|
+
class A extends Sigil {} // Throws: [Sigil Error] Class 'A' with label 'A' is already sigilified
|
|
292
|
+
|
|
293
|
+
class _A extends Sigil {}
|
|
294
|
+
withSigil(withSigil(_A, 'A'), 'B'); // Throws: [Sigil Error] Class 'A' with label 'A' is already sigilified
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
#### No label is passed with `autofillLabels: false`
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
updateSigilOptions({ autofillLabels: false });
|
|
301
|
+
|
|
302
|
+
class A extends Sigil {}
|
|
303
|
+
new A(); // Throws: [Sigil Error] Class 'A' is not sigilified, Make sure to sigilify all Sigil classes or set 'autofillLabels' to 'true'
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
#### Same label is passed twice to `Sigil`
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
@WithSigil('Label')
|
|
310
|
+
class A extends Sigil {}
|
|
311
|
+
|
|
312
|
+
@WithSigil('Label')
|
|
313
|
+
class B extends Sigil {} // Throws: [Sigil Error] Passed label 'Label' to class 'B' is re-used, passed labels must be unique
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
#### Invalid label format
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
updateSigilOptions({ labelValidation: RECOMMENDED_LABEL_REGEX });
|
|
320
|
+
|
|
321
|
+
@WithSigil('InvalidLabel')
|
|
322
|
+
class A extends Sigil {} // Throws: [Sigil Error] Invalid Sigil label 'InvalidLabel'. Make sure that supplied label matches validation regex or function
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
#### Using '@Sigil-auto' prefix
|
|
326
|
+
|
|
327
|
+
```ts
|
|
328
|
+
@WithSigil('@Sigil-auto:label')
|
|
329
|
+
class X extends Sigil {} // Throws: '@Sigil-auto' is a prefex reserved by the library
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
#### Invalid options passed to `updateOptions`
|
|
333
|
+
|
|
334
|
+
```ts
|
|
335
|
+
updateSigilOptions({ autofillLabels: {} as any }); // Throws: 'updateSigilOptions.autofillLabels' must be boolean
|
|
336
|
+
updateSigilOptions({ labelValidation: 123 as any }); // Throws: 'updateSigilOptions.labelValidation' must be null, function or RegExp
|
|
254
337
|
```
|
|
255
338
|
|
|
256
339
|
---
|
|
@@ -276,10 +359,11 @@ type test2 = User extends Admin ? true : false; // false
|
|
|
276
359
|
- **Helpers:**
|
|
277
360
|
- `isSigilCtor(ctor)`
|
|
278
361
|
- `isSigilInstance(inst)`
|
|
362
|
+
- `getSigilLabels(includeAuto?)`
|
|
279
363
|
|
|
280
364
|
- **Options:**
|
|
281
365
|
- `updateSigilOptions(opts)`
|
|
282
|
-
- `
|
|
366
|
+
- `RECOMMENDED_LABEL_REGEX`
|
|
283
367
|
|
|
284
368
|
- **Types:**
|
|
285
369
|
- `ISigil<Label, ParentSigil?>`
|
|
@@ -300,12 +384,13 @@ type test2 = User extends Admin ? true : false; // false
|
|
|
300
384
|
- `withSigil(Class, label, opts?)`: HOF that validates and decorates an existing class constructor.
|
|
301
385
|
- `isSigilCtor(value)`: `true` if `value` is a `Sigil` constructor.
|
|
302
386
|
- `isSigilInstance(value)`: `true` if `value` is an instance of a `Sigil` constructor.
|
|
387
|
+
- `getSigilLabels(includeAuto?)`: Get all `Sigil` labels registered, can include auto-generated labels as well.
|
|
303
388
|
- `updateSigilOptions(opts)`: change global runtime options of `Sigil` library (e.g., `autofillLabels`).
|
|
304
|
-
- `
|
|
389
|
+
- `RECOMMENDED_LABEL_REGEX`: regex that ensures structure of `@scope/package.ClassName` to all labels, it's advised to use it as your `SigilOptions.labelValidation`
|
|
305
390
|
|
|
306
391
|
### Instance & static helpers provided by Sigilified constructors
|
|
307
392
|
|
|
308
|
-
When a constructor is
|
|
393
|
+
When a constructor is sigilified it will expose the following **static** getters/methods:
|
|
309
394
|
|
|
310
395
|
- `SigilLabel` — the identity label string.
|
|
311
396
|
- `SigilEffectiveLabel` — the human label string.
|
|
@@ -418,7 +503,9 @@ npm run bench
|
|
|
418
503
|
|
|
419
504
|
## Bundle Size
|
|
420
505
|
|
|
421
|
-
**Less than 1.
|
|
506
|
+
**Less than 1.6 KB (1.51 KB)** (minified + Brotli, including all dependencies)
|
|
507
|
+
|
|
508
|
+
This makes Sigil one of the smallest full-featured solutions for nominal typing + reliable runtime identity.
|
|
422
509
|
|
|
423
510
|
**Running Tests**
|
|
424
511
|
|
|
@@ -429,8 +516,6 @@ npm install
|
|
|
429
516
|
npm run size
|
|
430
517
|
```
|
|
431
518
|
|
|
432
|
-
This makes Sigil one of the smallest full-featured solutions for nominal typing + reliable runtime identity.
|
|
433
|
-
|
|
434
519
|
---
|
|
435
520
|
|
|
436
521
|
## Tests
|
package/dist/index.d.mts
CHANGED
|
@@ -218,6 +218,9 @@ declare const SigilError: {
|
|
|
218
218
|
} & ErrorConstructor;
|
|
219
219
|
type SigilError = InstanceType<typeof SigilError>;
|
|
220
220
|
|
|
221
|
+
/** -----------------------------------------
|
|
222
|
+
* Types
|
|
223
|
+
* ----------------------------------------- */
|
|
221
224
|
/**
|
|
222
225
|
* Configuration options for the Sigil library.
|
|
223
226
|
*
|
|
@@ -240,6 +243,9 @@ interface SigilOptions {
|
|
|
240
243
|
*/
|
|
241
244
|
autofillLabels?: boolean;
|
|
242
245
|
}
|
|
246
|
+
/** -----------------------------------------
|
|
247
|
+
* Update options
|
|
248
|
+
* ----------------------------------------- */
|
|
243
249
|
/**
|
|
244
250
|
* Update runtime options for the Sigil library.
|
|
245
251
|
* Call this early during application startup if you want non-default behavior.
|
|
@@ -257,6 +263,8 @@ declare const updateSigilOptions: (opts: SigilOptions) => void;
|
|
|
257
263
|
*
|
|
258
264
|
* It's advised to use this regex in 'SigilOptions.labelValidation'.
|
|
259
265
|
*/
|
|
266
|
+
declare const RECOMMENDED_LABEL_REGEX: RegExp;
|
|
267
|
+
/** @deprecated - Use 'RECOMMENDED_LABEL_REGEX' instead, will be removed in v4 */
|
|
260
268
|
declare const DEFAULT_LABEL_REGEX: RegExp;
|
|
261
269
|
|
|
262
270
|
/**
|
|
@@ -281,7 +289,7 @@ declare function WithSigil(label: string, opts?: SigilOptions): (value: Function
|
|
|
281
289
|
declare function withSigil<S extends Function>(Class: S, label: string, opts?: SigilOptions): S;
|
|
282
290
|
|
|
283
291
|
/** -----------------------------------------
|
|
284
|
-
*
|
|
292
|
+
* Inspection helpers
|
|
285
293
|
* ----------------------------------------- */
|
|
286
294
|
/**
|
|
287
295
|
* Runtime predicate that checks whether the provided value is a sigil constructor.
|
|
@@ -298,6 +306,13 @@ declare function isSigilCtor(ctor: unknown): ctor is ISigil;
|
|
|
298
306
|
* @returns `true` if `obj` is an instance produced by a sigil constructor.
|
|
299
307
|
*/
|
|
300
308
|
declare function isSigilInstance(inst: unknown): inst is ISigilInstance;
|
|
309
|
+
/**
|
|
310
|
+
* Helper function to get labels registered by 'Sigil'
|
|
311
|
+
*
|
|
312
|
+
* @param includeAuto - Flag to include auto-generated labels as well, default is 'false'.
|
|
313
|
+
* @returns Sigil labels registered
|
|
314
|
+
*/
|
|
315
|
+
declare function getSigilLabels(includeAuto?: boolean): string[];
|
|
301
316
|
|
|
302
317
|
/**
|
|
303
318
|
* Mixin factory that augments an existing class with Sigil runtime metadata and helpers.
|
|
@@ -336,7 +351,7 @@ declare function Sigilify<B extends Constructor, L extends string>(Base: B, labe
|
|
|
336
351
|
/**
|
|
337
352
|
* Returns the identity sigil label of this instance's constructor.
|
|
338
353
|
*
|
|
339
|
-
* @returns The label string if passed (e.g. '@scope/pkg.ClassName'), random label if not passed (e.g. '@Sigil-auto:ClassName:
|
|
354
|
+
* @returns The label string if passed (e.g. '@scope/pkg.ClassName'), random label if not passed (e.g. '@Sigil-auto:ClassName:1:pnf11bgl').
|
|
340
355
|
*/
|
|
341
356
|
getSigilLabel(): string;
|
|
342
357
|
/**
|
|
@@ -447,7 +462,7 @@ declare function SigilifyAbstract<B extends ConstructorAbstract, L extends strin
|
|
|
447
462
|
/**
|
|
448
463
|
* Returns the identity sigil label of this instance's constructor.
|
|
449
464
|
*
|
|
450
|
-
* @returns The label string if passed (e.g. '@scope/pkg.ClassName'), random label if not passed (e.g. '@Sigil-auto:ClassName:
|
|
465
|
+
* @returns The label string if passed (e.g. '@scope/pkg.ClassName'), random label if not passed (e.g. '@Sigil-auto:ClassName:1:pnf11bgl').
|
|
451
466
|
*/
|
|
452
467
|
getSigilLabel(): string;
|
|
453
468
|
/**
|
|
@@ -523,4 +538,4 @@ declare function SigilifyAbstract<B extends ConstructorAbstract, L extends strin
|
|
|
523
538
|
isExactType<T>(this: T, other: unknown): other is GetPrototype<T>;
|
|
524
539
|
}) & B;
|
|
525
540
|
|
|
526
|
-
export { DEFAULT_LABEL_REGEX, type ExtendSigil, type GetPrototype, type ISigil, type ISigilInstance, type ISigilStatic, Sigil, SigilError, type SigilOf, type SigilOptions, Sigilify, SigilifyAbstract, WithSigil, isSigilCtor, isSigilInstance, sigil, updateSigilOptions, withSigil };
|
|
541
|
+
export { DEFAULT_LABEL_REGEX, type ExtendSigil, type GetPrototype, type ISigil, type ISigilInstance, type ISigilStatic, RECOMMENDED_LABEL_REGEX, Sigil, SigilError, type SigilOf, type SigilOptions, Sigilify, SigilifyAbstract, WithSigil, getSigilLabels, isSigilCtor, isSigilInstance, sigil, updateSigilOptions, withSigil };
|
package/dist/index.d.ts
CHANGED
|
@@ -218,6 +218,9 @@ declare const SigilError: {
|
|
|
218
218
|
} & ErrorConstructor;
|
|
219
219
|
type SigilError = InstanceType<typeof SigilError>;
|
|
220
220
|
|
|
221
|
+
/** -----------------------------------------
|
|
222
|
+
* Types
|
|
223
|
+
* ----------------------------------------- */
|
|
221
224
|
/**
|
|
222
225
|
* Configuration options for the Sigil library.
|
|
223
226
|
*
|
|
@@ -240,6 +243,9 @@ interface SigilOptions {
|
|
|
240
243
|
*/
|
|
241
244
|
autofillLabels?: boolean;
|
|
242
245
|
}
|
|
246
|
+
/** -----------------------------------------
|
|
247
|
+
* Update options
|
|
248
|
+
* ----------------------------------------- */
|
|
243
249
|
/**
|
|
244
250
|
* Update runtime options for the Sigil library.
|
|
245
251
|
* Call this early during application startup if you want non-default behavior.
|
|
@@ -257,6 +263,8 @@ declare const updateSigilOptions: (opts: SigilOptions) => void;
|
|
|
257
263
|
*
|
|
258
264
|
* It's advised to use this regex in 'SigilOptions.labelValidation'.
|
|
259
265
|
*/
|
|
266
|
+
declare const RECOMMENDED_LABEL_REGEX: RegExp;
|
|
267
|
+
/** @deprecated - Use 'RECOMMENDED_LABEL_REGEX' instead, will be removed in v4 */
|
|
260
268
|
declare const DEFAULT_LABEL_REGEX: RegExp;
|
|
261
269
|
|
|
262
270
|
/**
|
|
@@ -281,7 +289,7 @@ declare function WithSigil(label: string, opts?: SigilOptions): (value: Function
|
|
|
281
289
|
declare function withSigil<S extends Function>(Class: S, label: string, opts?: SigilOptions): S;
|
|
282
290
|
|
|
283
291
|
/** -----------------------------------------
|
|
284
|
-
*
|
|
292
|
+
* Inspection helpers
|
|
285
293
|
* ----------------------------------------- */
|
|
286
294
|
/**
|
|
287
295
|
* Runtime predicate that checks whether the provided value is a sigil constructor.
|
|
@@ -298,6 +306,13 @@ declare function isSigilCtor(ctor: unknown): ctor is ISigil;
|
|
|
298
306
|
* @returns `true` if `obj` is an instance produced by a sigil constructor.
|
|
299
307
|
*/
|
|
300
308
|
declare function isSigilInstance(inst: unknown): inst is ISigilInstance;
|
|
309
|
+
/**
|
|
310
|
+
* Helper function to get labels registered by 'Sigil'
|
|
311
|
+
*
|
|
312
|
+
* @param includeAuto - Flag to include auto-generated labels as well, default is 'false'.
|
|
313
|
+
* @returns Sigil labels registered
|
|
314
|
+
*/
|
|
315
|
+
declare function getSigilLabels(includeAuto?: boolean): string[];
|
|
301
316
|
|
|
302
317
|
/**
|
|
303
318
|
* Mixin factory that augments an existing class with Sigil runtime metadata and helpers.
|
|
@@ -336,7 +351,7 @@ declare function Sigilify<B extends Constructor, L extends string>(Base: B, labe
|
|
|
336
351
|
/**
|
|
337
352
|
* Returns the identity sigil label of this instance's constructor.
|
|
338
353
|
*
|
|
339
|
-
* @returns The label string if passed (e.g. '@scope/pkg.ClassName'), random label if not passed (e.g. '@Sigil-auto:ClassName:
|
|
354
|
+
* @returns The label string if passed (e.g. '@scope/pkg.ClassName'), random label if not passed (e.g. '@Sigil-auto:ClassName:1:pnf11bgl').
|
|
340
355
|
*/
|
|
341
356
|
getSigilLabel(): string;
|
|
342
357
|
/**
|
|
@@ -447,7 +462,7 @@ declare function SigilifyAbstract<B extends ConstructorAbstract, L extends strin
|
|
|
447
462
|
/**
|
|
448
463
|
* Returns the identity sigil label of this instance's constructor.
|
|
449
464
|
*
|
|
450
|
-
* @returns The label string if passed (e.g. '@scope/pkg.ClassName'), random label if not passed (e.g. '@Sigil-auto:ClassName:
|
|
465
|
+
* @returns The label string if passed (e.g. '@scope/pkg.ClassName'), random label if not passed (e.g. '@Sigil-auto:ClassName:1:pnf11bgl').
|
|
451
466
|
*/
|
|
452
467
|
getSigilLabel(): string;
|
|
453
468
|
/**
|
|
@@ -523,4 +538,4 @@ declare function SigilifyAbstract<B extends ConstructorAbstract, L extends strin
|
|
|
523
538
|
isExactType<T>(this: T, other: unknown): other is GetPrototype<T>;
|
|
524
539
|
}) & B;
|
|
525
540
|
|
|
526
|
-
export { DEFAULT_LABEL_REGEX, type ExtendSigil, type GetPrototype, type ISigil, type ISigilInstance, type ISigilStatic, Sigil, SigilError, type SigilOf, type SigilOptions, Sigilify, SigilifyAbstract, WithSigil, isSigilCtor, isSigilInstance, sigil, updateSigilOptions, withSigil };
|
|
541
|
+
export { DEFAULT_LABEL_REGEX, type ExtendSigil, type GetPrototype, type ISigil, type ISigilInstance, type ISigilStatic, RECOMMENDED_LABEL_REGEX, Sigil, SigilError, type SigilOf, type SigilOptions, Sigilify, SigilifyAbstract, WithSigil, getSigilLabels, isSigilCtor, isSigilInstance, sigil, updateSigilOptions, withSigil };
|
package/dist/index.global.js
CHANGED
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
OPTIONS.labelValidation = val != null ? val : null;
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
|
-
var
|
|
22
|
+
var RECOMMENDED_LABEL_REGEX = /^@[\w-]+(?:\/[\w-]+)*\.[A-Z][A-Za-z0-9]*$/;
|
|
23
|
+
var DEFAULT_LABEL_REGEX = RECOMMENDED_LABEL_REGEX;
|
|
23
24
|
|
|
24
25
|
// src/symbols.ts
|
|
25
26
|
var __SIGIL__ = /* @__PURE__ */ Symbol.for("@vicin/sigil.__SIGIL__");
|
|
@@ -33,13 +34,8 @@
|
|
|
33
34
|
function handleSigil(ctor, label, opts) {
|
|
34
35
|
if (handledCtors.has(ctor)) return;
|
|
35
36
|
verifyLabel(ctor, label, opts);
|
|
36
|
-
|
|
37
|
-
if (label && ancLabelsMap.has(label))
|
|
38
|
-
throw new Error(
|
|
39
|
-
`[Sigil Error] Attempt to assign label '${label}' to class '${ctor == null ? void 0 : ctor.name}' but label is already used by parent '${ancLabelsMap.get(label)}', Make sure that every class has a unique label`
|
|
40
|
-
);
|
|
37
|
+
handleAncestors(ctor, opts);
|
|
41
38
|
sigilify(ctor, label != null ? label : generateRandomLabel(ctor));
|
|
42
|
-
handledCtors.add(ctor);
|
|
43
39
|
}
|
|
44
40
|
function handleAncestors(ctor, opts) {
|
|
45
41
|
var _a;
|
|
@@ -56,13 +52,12 @@
|
|
|
56
52
|
if (labelOwner.has(l)) {
|
|
57
53
|
if (!autofillLabels)
|
|
58
54
|
throw new Error(
|
|
59
|
-
`[Sigil Error] Class '${a2.name}' is not sigilified
|
|
55
|
+
`[Sigil Error] Class '${a2.name}' is not sigilified, Make sure to sigilify all Sigil classes or set 'autofillLabels' to 'true'`
|
|
60
56
|
);
|
|
61
57
|
sigilify(a2, generateRandomLabel(a2));
|
|
62
58
|
}
|
|
63
59
|
labelOwner.set(labelOf(a2), a2.name);
|
|
64
60
|
}
|
|
65
|
-
return labelOwner;
|
|
66
61
|
}
|
|
67
62
|
function sigilify(ctor, label) {
|
|
68
63
|
var _a;
|
|
@@ -106,6 +101,8 @@
|
|
|
106
101
|
enumerable: false,
|
|
107
102
|
writable: false
|
|
108
103
|
});
|
|
104
|
+
getLabelRegistry().add(label);
|
|
105
|
+
handledCtors.add(ctor);
|
|
109
106
|
}
|
|
110
107
|
function isSigilCtor(ctor) {
|
|
111
108
|
return typeof ctor === "function" && ctor.prototype && __SIGIL__ in ctor.prototype;
|
|
@@ -122,6 +119,30 @@
|
|
|
122
119
|
function lineageOf(ctor) {
|
|
123
120
|
return ctor.prototype[__LINEAGE__];
|
|
124
121
|
}
|
|
122
|
+
function getSigilLabels(includeAuto = false) {
|
|
123
|
+
const labels = getLabelRegistry().labels();
|
|
124
|
+
if (includeAuto) return labels;
|
|
125
|
+
return labels.filter((l) => !l.startsWith(AUTO_LABEL_PREFEX));
|
|
126
|
+
}
|
|
127
|
+
function getLabelRegistry() {
|
|
128
|
+
if ("__labelRegistry__" in globalThis) return globalThis.__labelRegistry__;
|
|
129
|
+
const labelSet = /* @__PURE__ */ new Set();
|
|
130
|
+
let count = 0;
|
|
131
|
+
const labelRegistry = {
|
|
132
|
+
has: (label) => labelSet.has(label),
|
|
133
|
+
add: (label) => labelSet.add(label),
|
|
134
|
+
labels: () => [...labelSet],
|
|
135
|
+
enc: () => ++count
|
|
136
|
+
};
|
|
137
|
+
Object.freeze(labelRegistry);
|
|
138
|
+
Object.defineProperty(globalThis, "__labelRegistry__", {
|
|
139
|
+
value: labelRegistry,
|
|
140
|
+
writable: false,
|
|
141
|
+
configurable: false,
|
|
142
|
+
enumerable: false
|
|
143
|
+
});
|
|
144
|
+
return labelRegistry;
|
|
145
|
+
}
|
|
125
146
|
function verifyLabel(ctor, label, opts) {
|
|
126
147
|
var _a, _b;
|
|
127
148
|
const labelValidation = (_a = opts == null ? void 0 : opts.labelValidation) != null ? _a : OPTIONS.labelValidation;
|
|
@@ -129,31 +150,28 @@
|
|
|
129
150
|
if (!label) {
|
|
130
151
|
if (!autofillLabels)
|
|
131
152
|
throw new Error(
|
|
132
|
-
`[Sigil Error] Class '${ctor == null ? void 0 : ctor.name}' is not sigilified
|
|
153
|
+
`[Sigil Error] Class '${ctor == null ? void 0 : ctor.name}' is not sigilified, Make sure to sigilify all Sigil classes or set 'autofillLabels' to 'true'`
|
|
133
154
|
);
|
|
134
155
|
return;
|
|
135
156
|
}
|
|
136
157
|
if (label.startsWith(AUTO_LABEL_PREFEX))
|
|
137
158
|
throw new Error(`'${AUTO_LABEL_PREFEX}' is a prefex reserved by the library`);
|
|
159
|
+
if (getLabelRegistry().has(label))
|
|
160
|
+
throw new Error(
|
|
161
|
+
`[Sigil Error] Passed label '${label}' to class '${ctor == null ? void 0 : ctor.name}' is re-used, passed labels must be unique`
|
|
162
|
+
);
|
|
138
163
|
if (labelValidation) {
|
|
139
164
|
let valid;
|
|
140
165
|
if (labelValidation instanceof RegExp) valid = labelValidation.test(label);
|
|
141
166
|
else valid = labelValidation(label);
|
|
142
167
|
if (!valid)
|
|
143
168
|
throw new Error(
|
|
144
|
-
`[Sigil Error] Invalid
|
|
169
|
+
`[Sigil Error] Invalid Sigil label '${label}'. Make sure that supplied label matches validation regex or function`
|
|
145
170
|
);
|
|
146
171
|
}
|
|
147
172
|
}
|
|
148
|
-
function initCounter() {
|
|
149
|
-
if (!globalThis.__SigilabelCounter) globalThis.__SigilabelCounter = 0;
|
|
150
|
-
}
|
|
151
173
|
function generateRandomLabel(ctor) {
|
|
152
|
-
|
|
153
|
-
const counter = globalThis.__SigilabelCounter++;
|
|
154
|
-
const time = Date.now().toString(36);
|
|
155
|
-
const rand = Math.random().toString(36).slice(2, 6);
|
|
156
|
-
return `${AUTO_LABEL_PREFEX}:${ctor == null ? void 0 : ctor.name}:${time}:${counter.toString(36)}:${rand}`;
|
|
174
|
+
return `${AUTO_LABEL_PREFEX}:${ctor == null ? void 0 : ctor.name}:${getLabelRegistry().enc()}:${Math.random().toString(36).slice(2, 10)}`;
|
|
157
175
|
}
|
|
158
176
|
|
|
159
177
|
// src/mixin.ts
|
|
@@ -271,7 +289,7 @@
|
|
|
271
289
|
/**
|
|
272
290
|
* Returns the identity sigil label of this instance's constructor.
|
|
273
291
|
*
|
|
274
|
-
* @returns The label string if passed (e.g. '@scope/pkg.ClassName'), random label if not passed (e.g. '@Sigil-auto:ClassName:
|
|
292
|
+
* @returns The label string if passed (e.g. '@scope/pkg.ClassName'), random label if not passed (e.g. '@Sigil-auto:ClassName:1:pnf11bgl').
|
|
275
293
|
*/
|
|
276
294
|
getSigilLabel() {
|
|
277
295
|
return this[__LABEL__];
|
|
@@ -418,7 +436,7 @@
|
|
|
418
436
|
/**
|
|
419
437
|
* Returns the identity sigil label of this instance's constructor.
|
|
420
438
|
*
|
|
421
|
-
* @returns The label string if passed (e.g. '@scope/pkg.ClassName'), random label if not passed (e.g. '@Sigil-auto:ClassName:
|
|
439
|
+
* @returns The label string if passed (e.g. '@scope/pkg.ClassName'), random label if not passed (e.g. '@Sigil-auto:ClassName:1:pnf11bgl').
|
|
422
440
|
*/
|
|
423
441
|
getSigilLabel() {
|
|
424
442
|
return this[__LABEL__];
|
|
@@ -487,11 +505,13 @@
|
|
|
487
505
|
}
|
|
488
506
|
|
|
489
507
|
exports.DEFAULT_LABEL_REGEX = DEFAULT_LABEL_REGEX;
|
|
508
|
+
exports.RECOMMENDED_LABEL_REGEX = RECOMMENDED_LABEL_REGEX;
|
|
490
509
|
exports.Sigil = Sigil;
|
|
491
510
|
exports.SigilError = SigilError;
|
|
492
511
|
exports.Sigilify = Sigilify;
|
|
493
512
|
exports.SigilifyAbstract = SigilifyAbstract;
|
|
494
513
|
exports.WithSigil = WithSigil;
|
|
514
|
+
exports.getSigilLabels = getSigilLabels;
|
|
495
515
|
exports.isSigilCtor = isSigilCtor;
|
|
496
516
|
exports.isSigilInstance = isSigilInstance;
|
|
497
517
|
exports.updateSigilOptions = updateSigilOptions;
|