Skip to content

Commit eb50fa9

Browse files
committed
feat(errors): ERR_MISSING_ARGS
Signed-off-by: Lexus Drumgold <[email protected]>
1 parent 8e9d9f6 commit eb50fa9

9 files changed

+186
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ This package exports the following identifiers:
165165
- `ERR_INVALID_URL_SCHEME`
166166
- `ERR_INVALID_URL`
167167
- `ERR_METHOD_NOT_IMPLEMENTED`
168+
- `ERR_MISSING_ARGS`
168169
- `ERR_MISSING_OPTION`
169170
- `ERR_MODULE_NOT_FOUND`
170171
- `ERR_NETWORK_IMPORT_DISALLOWED`

src/__snapshots__/errors.integration.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ exports[`integration:errors > ERR_INVALID_URL_SCHEME > #toString > should return
4444

4545
exports[`integration:errors > ERR_METHOD_NOT_IMPLEMENTED > #toString > should return string representation of error 1`] = `Error [ERR_METHOD_NOT_IMPLEMENTED]: The _transform() method is not implemented`;
4646

47+
exports[`integration:errors > ERR_MISSING_ARGS > #toString > should return string representation of error 1`] = `TypeError [ERR_MISSING_ARGS]: The "address", "port", and "callback" arguments must be specified`;
48+
4749
exports[`integration:errors > ERR_MISSING_OPTION > #toString > should return string representation of error 1`] = `TypeError [ERR_MISSING_OPTION]: init.highWaterMark is required`;
4850

4951
exports[`integration:errors > ERR_MODULE_NOT_FOUND > #toString > should return string representation of error 1`] = `Error [ERR_MODULE_NOT_FOUND]: Cannot find module '\${process.cwd()}/missing-file' imported from \${process.cwd()}/src/__tests__/errors.integration.spec.ts`;

src/__snapshots__/index.e2e.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ exports[`e2e:errnode > should expose public api 1`] = `
2727
"ERR_INVALID_URL",
2828
"ERR_INVALID_URL_SCHEME",
2929
"ERR_METHOD_NOT_IMPLEMENTED",
30+
"ERR_MISSING_ARGS",
3031
"ERR_MISSING_OPTION",
3132
"ERR_MODULE_NOT_FOUND",
3233
"ERR_NETWORK_IMPORT_DISALLOWED",

src/__tests__/errors.integration.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ describe('integration:errors', () => {
8888
[codes.ERR_INVALID_URL, TypeError, pathe.sep, 'http://[127.0.0.1]:8000'],
8989
[codes.ERR_INVALID_URL_SCHEME, TypeError, 'file'],
9090
[codes.ERR_METHOD_NOT_IMPLEMENTED, Error, '_transform()'],
91+
[codes.ERR_MISSING_ARGS, TypeError, 'address', 'port', 'callback'],
9192
[codes.ERR_MISSING_OPTION, TypeError, 'init.highWaterMark'],
9293
[
9394
codes.ERR_MODULE_NOT_FOUND,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`unit:errors/ERR_MISSING_ARGS > should build message from parameters (0) 1`] = `"The "domain" argument must be specified"`;
4+
5+
exports[`unit:errors/ERR_MISSING_ARGS > should build message from parameters (1) 1`] = `"The "name" and "value" arguments must be specified"`;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* @file Type Tests - ERR_MISSING_ARGS
3+
* @module errnode/errors/tests/unit-d/ERR_MISSING_ARGS
4+
*/
5+
6+
import { codes } from '#src/enums'
7+
import type { NodeError, NodeErrorConstructor } from '#src/interfaces'
8+
import type * as TestSubject from '../err-missing-args'
9+
10+
describe('unit-d:errors/ERR_MISSING_ARGS', () => {
11+
describe('ERR_MISSING_ARGS', () => {
12+
it('should be ErrMissingArgsConstructor', () => {
13+
expectTypeOf<typeof TestSubject.default>()
14+
.toEqualTypeOf<TestSubject.ErrMissingArgsConstructor>()
15+
})
16+
})
17+
18+
describe('ErrMissingArgs', () => {
19+
it('should extend NodeError<codes.ERR_MISSING_ARGS>', () => {
20+
expectTypeOf<TestSubject.ErrMissingArgs>()
21+
.toMatchTypeOf<NodeError<codes.ERR_MISSING_ARGS>>()
22+
})
23+
24+
it('should extend TypeError', () => {
25+
expectTypeOf<TestSubject.ErrMissingArgs>()
26+
.toMatchTypeOf<TypeError>()
27+
})
28+
})
29+
30+
describe('ErrMissingArgsConstructor', () => {
31+
it('should match NodeErrorConstructor', () => {
32+
// Arrange
33+
type T = TestSubject.ErrMissingArgs
34+
type Args = TestSubject.ErrMissingArgsArgs
35+
36+
// Expect
37+
expectTypeOf<TestSubject.ErrMissingArgsConstructor>()
38+
.toMatchTypeOf<NodeErrorConstructor<T, Args>>()
39+
})
40+
})
41+
})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* @file Unit Tests - ERR_MISSING_ARGS
3+
* @module errnode/errors/tests/unit/ERR_MISSING_ARGS
4+
*/
5+
6+
import TestSubject, { type ErrMissingArgs } from '../err-missing-args'
7+
8+
describe('unit:errors/ERR_MISSING_ARGS', () => {
9+
it.each<Parameters<typeof TestSubject>>([
10+
['domain'],
11+
['name', 'value']
12+
])('should build message from parameters (%#)', (...args) => {
13+
// Act
14+
const subject: ErrMissingArgs = new TestSubject(...args)
15+
16+
// Expect
17+
expect(subject).to.have.property('message').be.a('string').that.is.not.empty
18+
expect(subject.message).toMatchSnapshot()
19+
})
20+
})

src/errors/err-missing-args.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/**
2+
* @file Errors - ERR_MISSING_ARGS
3+
* @module errnode/errors/ERR_MISSING_ARGS
4+
* @see https://github.com/nodejs/node/blob/v22.8.0/lib/internal/errors.js#L1565-L1579
5+
*/
6+
7+
import E from '#e'
8+
import { codes } from '#src/enums'
9+
import type { NodeError, NodeErrorConstructor } from '#src/interfaces'
10+
import { formatList } from '#src/utils'
11+
import { ok } from 'devlop'
12+
13+
/**
14+
* `ERR_MISSING_ARGS` schema.
15+
*
16+
* @see {@linkcode NodeError}
17+
* @see https://nodejs.org/api/errors.html#err_missing_args
18+
*
19+
* @extends {NodeError<codes.ERR_MISSING_ARGS>}
20+
* @extends {TypeError}
21+
*/
22+
interface ErrMissingArgs extends NodeError<codes.ERR_MISSING_ARGS>, TypeError {}
23+
24+
/**
25+
* `ERR_MISSING_ARGS` message arguments.
26+
*/
27+
type Args = [name: string | string[], ...names: (string | string[])[]]
28+
29+
/**
30+
* `ERR_MISSING_ARGS` constructor.
31+
*
32+
* @see {@linkcode Args}
33+
* @see {@linkcode ErrMissingArgs}
34+
* @see {@linkcode NodeErrorConstructor}
35+
*
36+
* @extends {NodeErrorConstructor<ErrMissingArgs,Args>}
37+
*/
38+
interface ErrMissingArgsConstructor
39+
extends NodeErrorConstructor<ErrMissingArgs, Args> {
40+
/**
41+
* Create a new `ERR_MISSING_ARGS` error.
42+
*
43+
* @see {@linkcode ErrMissingArgs}
44+
*
45+
* @param {string} name
46+
* Name of missing argument
47+
* @param {(string | string[])[]} names
48+
* List of missing arguments
49+
* @return {ErrMissingArgs}
50+
*/
51+
new (name: string, ...names: (string | string[])[]): ErrMissingArgs
52+
}
53+
54+
/**
55+
* `ERR_MISSING_ARGS` model.
56+
*
57+
* Thrown when a required argument of a Node.js API was not passed.
58+
*
59+
* @see {@linkcode ErrMissingArgsConstructor}
60+
*
61+
* @type {ErrMissingArgsConstructor}
62+
*
63+
* @class
64+
*/
65+
const ERR_MISSING_ARGS: ErrMissingArgsConstructor = E(
66+
codes.ERR_MISSING_ARGS,
67+
TypeError,
68+
/**
69+
* @param {(string | string[])[]} names
70+
* List of missing arguments
71+
* @return {string}
72+
* Error message
73+
*/
74+
function message(...names: (string | string[])[]): string {
75+
ok(names.length, 'At least one arg needs to be specified')
76+
77+
/**
78+
* Wrap a string in quotes.
79+
*
80+
* @param {string} a
81+
* String to wrap
82+
* @return {string}
83+
* Wrapped string
84+
*/
85+
const wrap = (a: string): string => `"${a}"`
86+
87+
/**
88+
* Error message.
89+
*
90+
* @var {string} message
91+
*/
92+
let message: string = 'The '
93+
94+
message += formatList(names.map(a => {
95+
/* c8 ignore next 2 */ return Array.isArray(a)
96+
? a.map(wrap).join(' or ')
97+
: wrap(a)
98+
}))
99+
100+
return `${message} argument${names.length > 1 ? 's' : ''} must be specified`
101+
}
102+
)
103+
104+
export {
105+
ERR_MISSING_ARGS as default,
106+
type ErrMissingArgs,
107+
type Args as ErrMissingArgsArgs,
108+
type ErrMissingArgsConstructor
109+
}

src/errors/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ export {
136136
type ErrMethodNotImplementedArgs,
137137
type ErrMethodNotImplementedConstructor
138138
} from './err-method-not-implemented'
139+
export {
140+
default as ERR_MISSING_ARGS,
141+
type ErrMissingArgs,
142+
type ErrMissingArgsArgs,
143+
type ErrMissingArgsConstructor
144+
} from './err-missing-args'
139145
export {
140146
default as ERR_MISSING_OPTION,
141147
type ErrMissingOption,

0 commit comments

Comments
 (0)