Skip to content

Commit 83ff48d

Browse files
committed
refactor(utils)!: [createNodeError] use class expression pattern
- https://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes - https://www.typescriptlang.org/docs/handbook/mixins.html Signed-off-by: Lexus Drumgold <unicornware@flexdevelopment.llc>
1 parent 851f107 commit 83ff48d

File tree

58 files changed

+993
-605
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+993
-605
lines changed

README.md

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,11 @@ interface ErrInvalidUrl extends NodeError<TypeError> {
141141
* @class
142142
*
143143
* @param {string} input - URL that failed to parse
144-
* @return {ErrInvalidUrl} `TypeError` instance
144+
* @return {ErrInvalidUrl} New `TypeError` instance
145145
*/
146146
const ERR_INVALID_URL: NodeErrorConstructor<
147-
TypeErrorConstructor,
148-
MessageFn<[string]>,
149-
ErrInvalidUrl
147+
ErrInvalidUrl,
148+
MessageFn<[string]>
150149
> = createNodeError(
151150
ErrorCode.ERR_INVALID_URL,
152151
TypeError,
@@ -244,7 +243,7 @@ There is no default export.
244243

245244
### Error Models
246245

247-
Constructor functions representing [Node.js error codes][7], callable with and without the `new` keyword. Constructor
246+
Constructor functions representing [Node.js error codes][7], callable **only** with the `new` keyword. Constructor
248247
arguments are used to generate error messages.
249248

250249
Models can be imported individually:
@@ -578,15 +577,15 @@ Thrown when an unsupported URL scheme is used in an `import` statement. URL sche
578577

579578
Creates a Node.js error constructor.
580579

581-
If the given error `message` is a function, constructor arguments are passed to `message`. If the `message` is a string,
582-
constructor arguments are passed to [`util.format`][15] instead.
580+
Constructor arguments are passed to [`util.format`][15] if the error `message` is a string, or `message` itself if it is
581+
a function. Message functions will also be called with the new Node.js error instance as `this`.
583582

584583
- `{ErrorCode}` **`code`** &mdash; Node.js error code
585-
- `{B extends ErrorConstructor}` **`Base`** &mdash; Error base class
586-
- `{M extends MessageFn | unknown[] | string}` **`message`** &mdash; Error message or message function
587-
- **Returns**: `{NodeErrorConstructor<B, M>}` `NodeError` constructor
584+
- `{ErrnodeConstructor}` **`Base`** &mdash; Error base class
585+
- `{Message}` **`message`** &mdash; Error message string or function
586+
- **Returns**: `{NodeErrorConstructor` `NodeError` constructor
588587

589-
> **Source**: [`src/create-node-error.ts`](src/create-node-error.ts)
588+
> **Source**: [`src/utils/create-node-error.ts`](src/utils/create-node-error.ts)
590589
591590
#### `determineSpecificType(value)`
592591

@@ -595,7 +594,7 @@ Determines the specific type of a value for type-mismatch errors.
595594
- `{unknown}` **`value`** &mdash; Value to evaluate
596595
- **Returns**: `{string}` Specific type of `value`
597596

598-
> **Source**: [`src/determine-specific-type.ts`](src/determine-specific-type.ts)
597+
> **Source**: [`src/utils/determine-specific-type.ts`](src/utils/determine-specific-type.ts)
599598
600599
## Types
601600

@@ -608,14 +607,17 @@ This package is fully typed with [TypeScript][16]. It exports the following defi
608607

609608
### Interfaces
610609

610+
- [`CallSite`](src/interfaces/call-site.ts)
611611
- [`ErrInvalidUrl`](src/interfaces/err-invalid-url.ts)
612612
- [`ErrnoException`](src/interfaces/errno-exception.ts)
613+
- [`NodeErrorConstructor`](src/interfaces/node-error-constructor.ts)
613614

614615
### Type Definitions
615616

616-
- [`NodeError`](src/types/node-error.ts)
617-
- [`NodeErrorConstructor`](src/types/node-error-constructor.ts)
617+
- [`ErrnodeConstructor`](src/types/errnode-constructor.ts)
618618
- [`MessageFn`](src/types/fn-message.ts)
619+
- [`Message`](src/types/message.ts)
620+
- [`NodeError`](src/types/node-error.ts)
619621

620622
## Contribute
621623

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/**
2+
* @file Type Tests - CallSite
3+
* @module errnode/interfaces/tests/unit-d/CallSite
4+
*/
5+
6+
import type { Fn, Nullable, Optional } from '@flex-development/tutils'
7+
import type TestSubject from '../call-site'
8+
9+
describe('unit-d:interfaces/CallSite', () => {
10+
it('should extend NodeJS.CallSite', () => {
11+
expectTypeOf<TestSubject>().toMatchTypeOf<NodeJS.CallSite>()
12+
})
13+
14+
it('should match [getColumnNumber(): Nullable<number>]', () => {
15+
expectTypeOf<TestSubject>()
16+
.toHaveProperty('getColumnNumber')
17+
.toEqualTypeOf<() => Nullable<number>>()
18+
})
19+
20+
it('should match [getEvalOrigin(): Optional<string>', () => {
21+
expectTypeOf<TestSubject>()
22+
.toHaveProperty('getEvalOrigin')
23+
.toEqualTypeOf<() => Optional<string>>()
24+
})
25+
26+
it('should match [getFileName(): Optional<string>]', () => {
27+
expectTypeOf<TestSubject>()
28+
.toHaveProperty('getFileName')
29+
.toEqualTypeOf<() => Optional<string>>()
30+
})
31+
32+
it('should match [getFunction(): Optional<Fn>]', () => {
33+
expectTypeOf<TestSubject>()
34+
.toHaveProperty('getFunction')
35+
.toEqualTypeOf<() => Optional<Fn>>()
36+
})
37+
38+
it('should match [getFunctionName(): Nullable<Fn["name"]>', () => {
39+
expectTypeOf<TestSubject>()
40+
.toHaveProperty('getFunctionName')
41+
.toEqualTypeOf<() => Nullable<Fn['name']>>()
42+
})
43+
44+
it('should match [getLineNumber(): Nullable<number>]', () => {
45+
expectTypeOf<TestSubject>()
46+
.toHaveProperty('getLineNumber')
47+
.toEqualTypeOf<() => Nullable<number>>()
48+
})
49+
50+
it('should match [getMethodName(): Nullable<string>]', () => {
51+
expectTypeOf<TestSubject>()
52+
.toHaveProperty('getMethodName')
53+
.toEqualTypeOf<() => Nullable<string>>()
54+
})
55+
56+
it('should match [getThis(): unknown]', () => {
57+
expectTypeOf<TestSubject>()
58+
.toHaveProperty('getThis')
59+
.toMatchTypeOf<() => unknown>()
60+
})
61+
62+
it('should match [getTypeName(): Nullable<string>', () => {
63+
expectTypeOf<TestSubject>()
64+
.toHaveProperty('getTypeName')
65+
.toEqualTypeOf<() => Nullable<string>>()
66+
})
67+
68+
it('should match [isConstructor(): boolean', () => {
69+
expectTypeOf<TestSubject>()
70+
.toHaveProperty('isConstructor')
71+
.toEqualTypeOf<() => boolean>()
72+
})
73+
74+
it('should match [isEval(): boolean', () => {
75+
expectTypeOf<TestSubject>()
76+
.toHaveProperty('isEval')
77+
.toEqualTypeOf<() => boolean>()
78+
})
79+
80+
it('should match [isNative(): boolean', () => {
81+
expectTypeOf<TestSubject>()
82+
.toHaveProperty('isNative')
83+
.toEqualTypeOf<() => boolean>()
84+
})
85+
86+
it('should match [isToplevel(): boolean', () => {
87+
expectTypeOf<TestSubject>()
88+
.toHaveProperty('isToplevel')
89+
.toEqualTypeOf<() => boolean>()
90+
})
91+
})
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* @file Type Tests - NodeErrorConstructor
3+
* @module errnode/interfaces/tests/unit-d/NodeErrorConstructor
4+
*/
5+
6+
import type { MessageFn, NodeError } from '#src/types'
7+
import type {
8+
Fn,
9+
Optional,
10+
Pick,
11+
Times,
12+
Writable
13+
} from '@flex-development/tutils'
14+
import type CallSite from '../call-site'
15+
import type ErrInvalidUrl from '../err-invalid-url'
16+
import type TestSubject from '../node-error-constructor'
17+
18+
describe('unit-d:interfaces/NodeErrorConstructor', () => {
19+
it('should construct NodeError<T>', () => {
20+
// Arrange
21+
type T = TypeError
22+
23+
// Expect
24+
expectTypeOf<TestSubject<T>>().instance.toEqualTypeOf<NodeError<T>>()
25+
})
26+
27+
it('should match [captureStackTrace(err: Error, ctor?: Fn): void]', () => {
28+
expectTypeOf<TestSubject>()
29+
.toHaveProperty('captureStackTrace')
30+
.toEqualTypeOf<(err: Error, ctor?: Fn) => void>()
31+
})
32+
33+
it('should match [prepareStackTrace?(err: Error, traces: CallSite[]): any]', () => {
34+
expectTypeOf<TestSubject>()
35+
.toHaveProperty('prepareStackTrace')
36+
.toMatchTypeOf<Optional<Fn<[Error, CallSite[]]>>>()
37+
})
38+
39+
it('should match [readonly prototype: NodeError<T>]', () => {
40+
// Arrange
41+
type T = ErrInvalidUrl
42+
type M = MessageFn<Times<1, string>>
43+
44+
// Expect
45+
expectTypeOf<Pick<TestSubject<T, M>, 'prototype'>>().toEqualTypeOf<{
46+
readonly prototype: NodeError<T>
47+
}>()
48+
})
49+
50+
it('should match [stackTraceLimit: number]', () => {
51+
expectTypeOf<TestSubject>()
52+
.toHaveProperty('stackTraceLimit')
53+
.toEqualTypeOf<number>()
54+
})
55+
56+
describe('M extends MessageFn', () => {
57+
it('should be callable with Parameters<M>', () => {
58+
// Arrange
59+
type T = RangeError
60+
type M = MessageFn<[string, number]>
61+
62+
// Expect
63+
expectTypeOf<TestSubject<T, M>>().constructorParameters.toEqualTypeOf<
64+
Parameters<M>
65+
>()
66+
})
67+
})
68+
69+
describe('M extends readonly unknown[]', () => {
70+
it('should be callable with Writable<M>', () => {
71+
// Arrange
72+
type T = SyntaxError
73+
type M = Readonly<Times<2, string>>
74+
75+
// Expect
76+
expectTypeOf<TestSubject<T, M>>().constructorParameters.toEqualTypeOf<
77+
Writable<M>
78+
>()
79+
})
80+
})
81+
82+
describe('M extends string', () => {
83+
it('should be callable with any[]', () => {
84+
expectTypeOf<TestSubject<TypeError, string>>()
85+
.constructorParameters.extract<any[]>()
86+
.not.toBeNever()
87+
})
88+
})
89+
})

src/interfaces/call-site.ts

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/**
2+
* @file Interfaces - CallSite
3+
* @module errnode/interfaces/CallSite
4+
*/
5+
6+
import type { Fn, Nullable, Optional } from '@flex-development/tutils'
7+
8+
/**
9+
* Object representing a stack frame.
10+
*
11+
* @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces
12+
*/
13+
interface CallSite {
14+
/**
15+
* Returns the current column number of the script the function was defined
16+
* in.
17+
*
18+
* @return {Nullable<number>} Current column number or `null`
19+
*/
20+
getColumnNumber(): Nullable<number>
21+
22+
/**
23+
* Returns a string representing the location where `eval` was called if the
24+
* current function was created using a call to `eval`.
25+
*
26+
* @return {Optional<string>} Location `eval` was called or `undefined`
27+
*/
28+
getEvalOrigin(): Optional<string>
29+
30+
/**
31+
* Returns the name of the script containing the current function if the
32+
* function was defined in a script.
33+
*
34+
* @return {Optional<string>} Parent script name or `undefined`
35+
*/
36+
getFileName(): Optional<string>
37+
38+
/**
39+
* Returns the current function.
40+
*
41+
* @return {Optional<Fn>} Current function or `undefined`
42+
*/
43+
getFunction(): Optional<Fn>
44+
45+
/**
46+
* Returns the name of the current function, typically its `name` property.
47+
*
48+
* If a `name` property is not available, an attempt is made to infer a name
49+
* from the function’s context.
50+
*
51+
* @return {Nullable<Fn['name']>} Current function name or `null`
52+
*/
53+
getFunctionName(): Nullable<Fn['name']>
54+
55+
/**
56+
* Returns the current line number of the script the function was defined in.
57+
*
58+
* @return {Nullable<number>} Current line number or `null`
59+
*/
60+
getLineNumber(): Nullable<number>
61+
62+
/**
63+
* Returns the name of the `this` property or one of its prototypes that holds
64+
* the current function.
65+
*
66+
* @return {Nullable<string>} Property containing current function or `null`
67+
*/
68+
getMethodName(): Nullable<string>
69+
70+
/**
71+
* Returns the value of `this`.
72+
*
73+
* @template T - `this` type
74+
*
75+
* @return {T} Value of `this`
76+
*/
77+
getThis<T = unknown>(): T
78+
79+
/**
80+
* Returns the type of `this` as a string.
81+
*
82+
* This is the name of the function stored in the constructor field of `this`,
83+
* if available, otherwise the object’s `[[Class]]` internal property.
84+
*
85+
* @return {Nullable<string>} Type of `this` as a string or `null`
86+
*/
87+
getTypeName(): Nullable<string>
88+
89+
/**
90+
* Returns a boolean indicating if the current call is a constructor call.
91+
*
92+
* @return {boolean} `true` if call is constructor call
93+
*/
94+
isConstructor(): boolean
95+
96+
/**
97+
* Returns a boolean indicating if the current call took place in code defined
98+
* by a call to `eval`.
99+
*
100+
* @return {boolean} `true` if call takes place in code defined by `eval`
101+
*/
102+
isEval(): boolean
103+
104+
/**
105+
* Returns a boolean indicating if the current call is in native V8 code.
106+
*
107+
* @return {boolean} `true` if call is in native V8 code
108+
*/
109+
isNative(): boolean
110+
111+
/**
112+
* Returns a boolean indicating the current call is a top-level invocation.
113+
*
114+
* @return {boolean} `true` if call is top-level invocation
115+
*/
116+
isToplevel(): boolean
117+
}
118+
119+
export type { CallSite as default }

0 commit comments

Comments
 (0)