Skip to content
This repository was archived by the owner on Apr 8, 2025. It is now read-only.

Commit cf0028a

Browse files
committed
Merge branch 'feature/bslt-143' into develop
2 parents eb35f13 + 8f0cdde commit cf0028a

File tree

19 files changed

+130
-304
lines changed

19 files changed

+130
-304
lines changed

bundler.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ await Bun.build({
1414
'./source/error/index.ts',
1515
'./source/error/key/index.ts',
1616

17-
'./source/i18n/index.ts',
18-
1917
'./source/types/index.ts',
2018

2119
'./source/index.ts'

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
"./auth": "./build/core/index.js",
2727
"./error": "./build/error/index.js",
2828
"./error/key": "./build/error/key/index.js",
29-
"./i18n": "./build/i18n/index.js",
3029
"./types": "./build/types/index.js",
3130
".": "./build/index.js"
3231
},

source/core/basaltToken.ts

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { randomUUIDv7 } from 'bun';
22
import { sign as sig, verify as ver } from 'crypto';
33

44
import { BasaltError } from '#/error/basaltError';
5-
import { GLOBAL_KEY_ERROR } from '#/error/key/globalKeyError';
5+
import { TOKEN_KEY_ERROR } from '#/error/key/tokenKeyError';
66
import { base64Decode, base64Encode } from '#/tools/base64.util';
77
import { generateKeyPairED25519 } from '#/tools/keyGenerator.util';
88
import type { BasaltTokenHeader } from '#/types/data/basaltTokenHeader';
@@ -91,15 +91,16 @@ function _buildSignature(header: string, payload: string, privateKey: string, pa
9191
*
9292
* @param token - The authentication token.
9393
*
94-
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link GLOBAL_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
95-
* @throws ({@link BasaltError}) If the token header is invalid. ({@link GLOBAL_KEY_ERROR.TOKEN_INVALID_HEADER})
94+
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link TOKEN_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
95+
* @throws ({@link BasaltError}) If the token header is invalid. ({@link TOKEN_KEY_ERROR.TOKEN_INVALID_HEADER})
9696
*
9797
* @returns The parsed header of the token. ({@link BasaltTokenHeader})
9898
*/
9999
function getHeader(token: string): BasaltTokenHeader {
100100
if (!_structureIsValid(token))
101101
throw new BasaltError({
102-
key: GLOBAL_KEY_ERROR.TOKEN_INVALID_STRUCTURE
102+
key: TOKEN_KEY_ERROR.TOKEN_INVALID_STRUCTURE,
103+
message: 'Token structure is invalid.'
103104
});
104105
const [header]: string[] = token.split('.');
105106
try {
@@ -108,7 +109,8 @@ function getHeader(token: string): BasaltTokenHeader {
108109
) as BasaltTokenHeader;
109110
} catch {
110111
throw new BasaltError({
111-
key: GLOBAL_KEY_ERROR.TOKEN_INVALID_HEADER
112+
key: TOKEN_KEY_ERROR.TOKEN_INVALID_HEADER,
113+
message: 'Token header is invalid.'
112114
});
113115
}
114116
}
@@ -118,7 +120,7 @@ function getHeader(token: string): BasaltTokenHeader {
118120
*
119121
* @param token - The authentication token.
120122
*
121-
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link GLOBAL_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
123+
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link TOKEN_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
122124
*
123125
* @returns The UUID of the token.
124126
*/
@@ -131,7 +133,7 @@ function getTokenUuid(token: string): string {
131133
*
132134
* @param token - The authentication token.
133135
*
134-
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link GLOBAL_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
136+
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link TOKEN_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
135137
*
136138
* @returns The expiration date of the token.
137139
*/
@@ -144,7 +146,7 @@ function getExpirationDate(token: string): Date {
144146
*
145147
* @param token - The authentication token.
146148
*
147-
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link GLOBAL_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
149+
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link TOKEN_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
148150
*
149151
* @returns The intended audience of the token.
150152
*/
@@ -157,7 +159,7 @@ function getAudience(token: string): string {
157159
*
158160
* @param token - The authentication token.
159161
*
160-
* @throws ({@link BasaltError} If the token structure is invalid. ({@link GLOBAL_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
162+
* @throws ({@link BasaltError} If the token structure is invalid. ({@link TOKEN_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
161163
*
162164
* @returns The issuer of the token.
163165
*/
@@ -172,15 +174,16 @@ function getIssuer(token: string): string {
172174
*
173175
* @param token - The authentication token.
174176
*
175-
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link GLOBAL_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
176-
* @throws ({@link BasaltError}) If the token payload is invalid. ({@link GLOBAL_KEY_ERROR.TOKEN_INVALID_PAYLOAD})
177+
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link TOKEN_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
178+
* @throws ({@link BasaltError}) If the token payload is invalid. ({@link TOKEN_KEY_ERROR.TOKEN_INVALID_PAYLOAD})
177179
*
178180
* @returns The parsed payload of the token. ({@link T})
179181
*/
180182
function getPayload<T extends object>(token: string): T {
181183
if (!_structureIsValid(token))
182184
throw new BasaltError({
183-
key: GLOBAL_KEY_ERROR.TOKEN_INVALID_STRUCTURE
185+
key: TOKEN_KEY_ERROR.TOKEN_INVALID_STRUCTURE,
186+
message: 'Token structure is invalid.'
184187
});
185188
const [, payload]: string[] = token.split('.');
186189
try {
@@ -189,7 +192,8 @@ function getPayload<T extends object>(token: string): T {
189192
) as T;
190193
} catch {
191194
throw new BasaltError({
192-
key: GLOBAL_KEY_ERROR.TOKEN_INVALID_PAYLOAD
195+
key: TOKEN_KEY_ERROR.TOKEN_INVALID_PAYLOAD,
196+
message: 'Token payload is invalid.'
193197
});
194198
}
195199
}
@@ -199,7 +203,7 @@ function getPayload<T extends object>(token: string): T {
199203
*
200204
* @param token - The authentication token.
201205
*
202-
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link GLOBAL_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
206+
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link TOKEN_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
203207
*
204208
* @returns True if the token has expired, false otherwise.
205209
*/
@@ -258,24 +262,27 @@ function sign<T extends object>(
258262
* @param token - The authentication token to verify.
259263
* @param publicKey - The public key corresponding to the private key used to sign the token.
260264
*
261-
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link GLOBAL_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
262-
* @throws ({@link BasaltError}) If the token has expired. ({@link GLOBAL_KEY_ERROR.TOKEN_IS_EXPIRED})
263-
* @throws ({@link BasaltError}) If the token signature is invalid. ({@link GLOBAL_KEY_ERROR.TOKEN_SIGNATURE_INVALID})
265+
* @throws ({@link BasaltError}) If the token structure is invalid. ({@link TOKEN_KEY_ERROR.TOKEN_INVALID_STRUCTURE})
266+
* @throws ({@link BasaltError}) If the token has expired. ({@link TOKEN_KEY_ERROR.TOKEN_IS_EXPIRED})
267+
* @throws ({@link BasaltError}) If the token signature is invalid. ({@link TOKEN_KEY_ERROR.TOKEN_SIGNATURE_INVALID})
264268
*/
265269
function verify(token: string, publicKey: string): void {
266270
if (isExpired(token))
267271
throw new BasaltError({
268-
key: GLOBAL_KEY_ERROR.TOKEN_IS_EXPIRED
272+
key: TOKEN_KEY_ERROR.TOKEN_IS_EXPIRED,
273+
message: 'Token has expired.'
269274
});
270275
const [header, payload, signature]: string[] = token.split('.');
271276
try {
272277
if (!ver(null, Buffer.from(`${header}.${payload}`), publicKey, Buffer.from(signature, 'base64')))
273278
throw new BasaltError({
274-
key: GLOBAL_KEY_ERROR.TOKEN_SIGNATURE_INVALID
279+
key: TOKEN_KEY_ERROR.TOKEN_SIGNATURE_INVALID,
280+
message: 'Token signature is invalid.'
275281
});
276282
} catch {
277283
throw new BasaltError({
278-
key: GLOBAL_KEY_ERROR.TOKEN_SIGNATURE_INVALID
284+
key: TOKEN_KEY_ERROR.TOKEN_SIGNATURE_INVALID,
285+
message: 'Token signature is invalid.'
279286
});
280287
}
281288
}

source/error/basaltError.ts

Lines changed: 63 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -5,168 +5,134 @@ import { randomUUIDv7 } from 'bun';
55
*/
66
export interface BasaltErrorOptions<T = unknown> {
77
/**
8-
* The error key.
8+
* The error message describing what went wrong.
99
*/
10-
key?: readonly [string, number] | undefined;
10+
message?: string;
11+
12+
/**
13+
* A unique key identifying the type of error, useful for localization or error handling.
14+
*/
15+
key?: string;
16+
17+
/**
18+
* The HTTP status code associated with the error, typically used in API responses.
19+
*/
20+
httpStatusCode?: number;
21+
1122
/**
12-
* The cause of the error.
23+
* The cause of the error, which can be an original error or additional context.
1324
*/
1425
cause?: T;
1526
}
1627

1728
/**
18-
* Basalt error class that extends the ({@link Error}) class and provides additional properties. (uuidError, date, code, fileName, line, column)
29+
* A custom error class that extends the native {@link Error} class, providing additional properties
30+
* such as a unique identifier, error key, HTTP status code, and cause.
1931
*
20-
* @typeParam T - The type of the cause of the error.
32+
* @typeParam T - The type of the cause of the error, which can be any object or error.
2133
*
2234
* @example
23-
* The following example demonstrates how to throw a new instance of the Basalt error.
35+
* The following example demonstrates how to throw and catch a BasaltError.
2436
* ```typescript
2537
* try {
26-
* throw new BasaltError();
38+
* throw new BasaltError({
39+
* message: 'An error occurred',
40+
* key: 'example.error',
41+
* httpStatusCode: 400,
42+
* cause: new Error('Original error')
43+
* });
2744
* } catch (error) {
28-
* console.log(error instanceof BasaltError); // true
29-
* console.log(error instanceof Error); // true
30-
* // u can access to uuidError, date, code, fileName, line, column, message, name, stack, cause, toJSON
45+
* if (error instanceof BasaltError) {
46+
* console.error(`Error UUID: ${error.uuid}`);
47+
* console.error(`Error Date: ${error.date}`);
48+
* console.error(`Error Key: ${error.key}`);
49+
* console.error(`HTTP Status Code: ${error.httpStatusCode}`);
50+
* console.error(`Cause: ${error.cause}`);
51+
* }
3152
* }
3253
* ```
54+
*
3355
* @example
34-
* The following example demonstrates how to create a new instance of the Basalt error with provided type for the cause.
56+
* The following example demonstrates how to create a BasaltError with a custom cause type.
3557
* ```typescript
36-
* // { foo: 'bar' } is the type of the cause;
37-
* const basaltError: BasaltError<{ foo: 'bar' }> = new BasaltError({
38-
* key: 'error.unknown',
39-
* cause: {
40-
* foo: 'bar',
41-
* },
58+
* const basaltError = new BasaltError<{ foo: string }>({
59+
* message: 'Custom error with cause',
60+
* key: 'basalt-package.error.custom_error',
61+
* httpStatusCode: 500,
62+
* cause: { foo: 'bar' },
4263
* });
4364
* console.log(basaltError.cause); // { foo: 'bar' }
4465
* ```
4566
*/
4667
export class BasaltError<const T = unknown> extends Error {
4768
/**
48-
* The cause of the error. (if available)
69+
* The cause of the error, typically used to store the original error or additional context.
4970
*/
5071
public override readonly cause: T | undefined;
5172

5273
/**
53-
* The unique identifier of the error.
54-
* This identifier is used to track the error in the logs.
74+
* The unique identifier of the error, automatically generated using UUID v7.
75+
* This identifier is particularly useful for tracking errors in logs.
5576
*/
5677
private readonly _uuid: string = randomUUIDv7();
5778

5879
/**
59-
* The date when the error was created.
80+
* The date when the error was created, automatically set to the current date and time.
6081
*/
6182
private readonly _date: Date = new Date();
6283

6384
/**
64-
* The error code. (HTTP status code)
65-
*/
66-
private readonly _statusCode: number;
67-
68-
/**
69-
* The fileName where the error occurred (if available).
70-
*/
71-
private readonly _fileName: string = '';
72-
73-
/**
74-
* The line number where the error occurred (if available).
85+
* A unique key identifying the type of error, useful for localization or error handling.
7586
*/
76-
private readonly _line: number = 0;
87+
private readonly _key: string;
7788

7889
/**
79-
* The column number where the error occurred (if available).
90+
* The HTTP status code associated with the error, typically used in API responses.
8091
*/
81-
private readonly _column: number = 0;
92+
private readonly _httpStatusCode: number;
8293

8394
/**
84-
* Creates a new instance of the Basalt error.
95+
* Creates a new instance of the BasaltError class.
8596
*
8697
* @param basaltErrorOptions - The options for the Basalt error. ({@link BasaltErrorOptions})
8798
*/
8899
public constructor(basaltErrorOptions?: Readonly<BasaltErrorOptions<T>>) {
89-
super(basaltErrorOptions?.key?.[0] || 'error.unknown');
100+
super(basaltErrorOptions?.message);
90101
super.name = 'BasaltError';
91102
this.cause = basaltErrorOptions?.cause;
92-
this._statusCode = basaltErrorOptions?.key?.[1] || 500;
93-
const stackLine = this.stack?.split('\n')[1]?.trim();
94-
const match = stackLine?.match(/\(?(.+):(\d+):(\d+)\)?$/);
95-
if (match) {
96-
this._fileName = match[1] || '';
97-
this._line = parseInt(match[2], 10) || 0;
98-
this._column = parseInt(match[3], 10) || 0;
99-
}
103+
this._key = basaltErrorOptions?.key || '';
104+
this._httpStatusCode = basaltErrorOptions?.httpStatusCode || 500;
100105
}
101106

102107
/**
103-
* The unique identifier of the error.
108+
* Gets the unique identifier of the error.
109+
* @returns The UUID of the error.
104110
*/
105111
public get uuid(): string {
106112
return this._uuid;
107113
}
108114

109115
/**
110-
* The date when the error was created.
116+
* Gets the date when the error was created.
117+
* @returns The creation date of the error.
111118
*/
112119
public get date(): Date {
113120
return this._date;
114121
}
115122

116123
/**
117-
* The error code. (HTTP status code)
124+
* Gets the error key, which identifies the type of error.
125+
* @returns The key associated with the error.
118126
*/
119-
public get statusCode(): number {
120-
return this._statusCode;
127+
public get key(): string {
128+
return this._key;
121129
}
122130

123131
/**
124-
* The fileName where the error occurred (if available).
132+
* Gets the HTTP status code associated with the error.
133+
* @returns The HTTP status code.
125134
*/
126-
public get fileName(): string {
127-
return this._fileName;
135+
public get httpStatusCode(): number {
136+
return this._httpStatusCode;
128137
}
129-
130-
/**
131-
* The line number where the error occurred (if available).
132-
*/
133-
public get line(): number {
134-
return this._line;
135-
}
136-
137-
/**
138-
* The column number where the error occurred (if available).
139-
*/
140-
public get column(): number {
141-
return this._column;
142-
}
143-
144-
/**
145-
* Converts the error object to a JSON object.
146-
*
147-
* @returns The error object as a JSON object.
148-
*/
149-
public toJSON(): {
150-
name: string;
151-
uuid: string;
152-
date: Date;
153-
message: string;
154-
statusCode: number;
155-
cause: T | undefined;
156-
fileName: string;
157-
line: number;
158-
column: number;
159-
} {
160-
return {
161-
name: this.name,
162-
uuid: this._uuid,
163-
date: this._date,
164-
message: this.message,
165-
statusCode: this._statusCode,
166-
cause: this.cause,
167-
fileName: this._fileName,
168-
line: this._line,
169-
column: this._column
170-
};
171-
}
172-
}
138+
}

0 commit comments

Comments
 (0)