najm-validation 0.1.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/dist/index.d.ts +201 -0
- package/dist/index.js +221 -0
- package/package.json +43 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import * as diject from 'diject';
|
|
2
|
+
import * as najm_core from 'najm-core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Validation target type
|
|
6
|
+
*/
|
|
7
|
+
type ValidationTarget = 'body' | 'params' | 'query' | 'headers';
|
|
8
|
+
/**
|
|
9
|
+
* Minimal schema shape required by validation plugin.
|
|
10
|
+
* Supports both Zod v3 and v4 schema instances.
|
|
11
|
+
*/
|
|
12
|
+
interface ValidationSchema {
|
|
13
|
+
parse(data: unknown): unknown;
|
|
14
|
+
strip?: () => ValidationSchema;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Minimal Zod issue shape used for error formatting.
|
|
18
|
+
*/
|
|
19
|
+
interface ZodIssueLike {
|
|
20
|
+
path: PropertyKey[];
|
|
21
|
+
message: string;
|
|
22
|
+
code: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Minimal Zod error shape used by framework internals.
|
|
26
|
+
* Compatible with Zod v3 and v4 errors.
|
|
27
|
+
*/
|
|
28
|
+
interface ZodErrorLike {
|
|
29
|
+
issues: ZodIssueLike[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Error formatter function type
|
|
33
|
+
*/
|
|
34
|
+
type ErrorFormatter = (error: ZodErrorLike, target: ValidationTarget) => any;
|
|
35
|
+
/**
|
|
36
|
+
* Validation configuration for @Validate decorator
|
|
37
|
+
*/
|
|
38
|
+
interface ValidationConfig {
|
|
39
|
+
/**
|
|
40
|
+
* Zod schema for request body validation
|
|
41
|
+
*/
|
|
42
|
+
body?: ValidationSchema;
|
|
43
|
+
/**
|
|
44
|
+
* Zod schema for route params validation
|
|
45
|
+
*/
|
|
46
|
+
params?: ValidationSchema;
|
|
47
|
+
/**
|
|
48
|
+
* Zod schema for query parameters validation
|
|
49
|
+
*/
|
|
50
|
+
query?: ValidationSchema;
|
|
51
|
+
/**
|
|
52
|
+
* Zod schema for request headers validation
|
|
53
|
+
*/
|
|
54
|
+
headers?: ValidationSchema;
|
|
55
|
+
/**
|
|
56
|
+
* Remove unknown fields from validated data (default: false)
|
|
57
|
+
*/
|
|
58
|
+
stripUnknown?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* HTTP status code for validation errors (default: 400)
|
|
61
|
+
*/
|
|
62
|
+
errorStatus?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Custom error formatter for validation errors
|
|
65
|
+
*/
|
|
66
|
+
errorFormatter?: ErrorFormatter;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Input type for @Validate decorator
|
|
70
|
+
* Can be a Zod schema (assumes body validation) or full config object
|
|
71
|
+
*/
|
|
72
|
+
type ValidateInput = ValidationSchema | ValidationConfig;
|
|
73
|
+
/**
|
|
74
|
+
* Plugin configuration options
|
|
75
|
+
*/
|
|
76
|
+
interface ValidationPluginConfig {
|
|
77
|
+
/**
|
|
78
|
+
* Enable or disable validation globally (default: true)
|
|
79
|
+
*/
|
|
80
|
+
enabled?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Default strip unknown fields behavior (default: false)
|
|
83
|
+
*/
|
|
84
|
+
stripUnknown?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Default HTTP status code for validation errors (default: 400)
|
|
87
|
+
*/
|
|
88
|
+
errorStatus?: number;
|
|
89
|
+
/**
|
|
90
|
+
* Global error formatter
|
|
91
|
+
*/
|
|
92
|
+
errorFormatter?: ErrorFormatter;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Metadata key for @Validate decorator
|
|
97
|
+
*/
|
|
98
|
+
declare const VALIDATE_META: unique symbol;
|
|
99
|
+
/**
|
|
100
|
+
* Configuration token for validation plugin
|
|
101
|
+
*/
|
|
102
|
+
declare const VALIDATION_CONFIG: unique symbol;
|
|
103
|
+
/**
|
|
104
|
+
* ALS tokens for validated request data
|
|
105
|
+
* Stored in AsyncLocalStorage for request-scoped access
|
|
106
|
+
*/
|
|
107
|
+
declare const VALIDATED_BODY: diject.AlsToken<any>;
|
|
108
|
+
declare const VALIDATED_PARAMS: diject.AlsToken<any>;
|
|
109
|
+
declare const VALIDATED_QUERY: diject.AlsToken<any>;
|
|
110
|
+
declare const VALIDATED_HEADERS: diject.AlsToken<any>;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @Validate decorator - Validates request data using Zod schemas
|
|
114
|
+
*
|
|
115
|
+
* Smart defaults: Pass a schema directly for body validation (most common use case)
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* // Body validation (90% use case)
|
|
119
|
+
* @Validate(CreateUserSchema)
|
|
120
|
+
* createUser(@Body() data) { ... }
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* // Multiple targets
|
|
124
|
+
* @Validate({
|
|
125
|
+
* body: CreateUserSchema,
|
|
126
|
+
* params: z.object({ id: z.string().uuid() })
|
|
127
|
+
* })
|
|
128
|
+
* updateUser(@Params('id') id, @Body() data) { ... }
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* // With options
|
|
132
|
+
* @Validate({
|
|
133
|
+
* body: CreateUserSchema,
|
|
134
|
+
* stripUnknown: true,
|
|
135
|
+
* errorStatus: 422
|
|
136
|
+
* })
|
|
137
|
+
* createUser(@Body() data) { ... }
|
|
138
|
+
*/
|
|
139
|
+
declare function Validate(input: ValidateInput): MethodDecorator;
|
|
140
|
+
/**
|
|
141
|
+
* Helper to retrieve validation config from metadata
|
|
142
|
+
*/
|
|
143
|
+
declare function getValidationConfig(target: any, methodName?: string | symbol): ValidationConfig | undefined;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Validation plugin factory
|
|
147
|
+
*
|
|
148
|
+
* Provides request validation using Zod schemas with smart defaults
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* // Default configuration
|
|
152
|
+
* const server = new Server()
|
|
153
|
+
* .use(validation())
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* // Custom configuration
|
|
157
|
+
* const server = new Server()
|
|
158
|
+
* .use(validation({
|
|
159
|
+
* stripUnknown: true,
|
|
160
|
+
* errorStatus: 422,
|
|
161
|
+
* errorFormatter: customFormatter
|
|
162
|
+
* }))
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* // Disable validation
|
|
166
|
+
* const server = new Server()
|
|
167
|
+
* .use(validation({ enabled: false }))
|
|
168
|
+
*/
|
|
169
|
+
declare const validation: (config?: ValidationPluginConfig) => najm_core.NajmPlugin;
|
|
170
|
+
|
|
171
|
+
declare class ValidationService {
|
|
172
|
+
private container;
|
|
173
|
+
private scanner;
|
|
174
|
+
private config;
|
|
175
|
+
private log;
|
|
176
|
+
private validationCount;
|
|
177
|
+
private defaultErrorStatus;
|
|
178
|
+
private defaultStripUnknown;
|
|
179
|
+
private defaultErrorFormatter?;
|
|
180
|
+
scan(): Promise<void>;
|
|
181
|
+
configure(): Promise<void>;
|
|
182
|
+
activate(): Promise<void>;
|
|
183
|
+
onReady(): Promise<void>;
|
|
184
|
+
/**
|
|
185
|
+
* Create validation middleware for a specific route
|
|
186
|
+
* Note: ctx param required by Hono but we use ALS internally
|
|
187
|
+
*/
|
|
188
|
+
private createValidationMiddleware;
|
|
189
|
+
/**
|
|
190
|
+
* Validate a specific request target using ALS
|
|
191
|
+
*/
|
|
192
|
+
private validateTarget;
|
|
193
|
+
private isZodErrorLike;
|
|
194
|
+
/**
|
|
195
|
+
* Extract data from ALS instead of ctx
|
|
196
|
+
*/
|
|
197
|
+
private extractData;
|
|
198
|
+
private throwValidationError;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export { type ErrorFormatter, VALIDATED_BODY, VALIDATED_HEADERS, VALIDATED_PARAMS, VALIDATED_QUERY, VALIDATE_META, VALIDATION_CONFIG, Validate, type ValidateInput, type ValidationConfig, type ValidationPluginConfig, type ValidationSchema, ValidationService, type ValidationTarget, type ZodErrorLike, type ZodIssueLike, getValidationConfig, validation };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
|
|
4
|
+
// src/tokens.ts
|
|
5
|
+
import { createAlsToken } from "najm-core";
|
|
6
|
+
var VALIDATE_META = /* @__PURE__ */ Symbol("validate");
|
|
7
|
+
var VALIDATION_CONFIG = /* @__PURE__ */ Symbol("validation:config");
|
|
8
|
+
var VALIDATED_BODY = createAlsToken("validated:body");
|
|
9
|
+
var VALIDATED_PARAMS = createAlsToken("validated:params");
|
|
10
|
+
var VALIDATED_QUERY = createAlsToken("validated:query");
|
|
11
|
+
var VALIDATED_HEADERS = createAlsToken("validated:headers");
|
|
12
|
+
|
|
13
|
+
// src/decorator.ts
|
|
14
|
+
import { MetaHelper } from "najm-core";
|
|
15
|
+
function isValidationSchema(value) {
|
|
16
|
+
return value !== null && value !== void 0 && typeof value === "object" && "parse" in value && typeof value.parse === "function";
|
|
17
|
+
}
|
|
18
|
+
__name(isValidationSchema, "isValidationSchema");
|
|
19
|
+
function Validate(input) {
|
|
20
|
+
const config = isValidationSchema(input) ? { body: input } : input;
|
|
21
|
+
return (target, methodName) => {
|
|
22
|
+
MetaHelper.define(VALIDATE_META, config, target[methodName]);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
__name(Validate, "Validate");
|
|
26
|
+
function getValidationConfig(target, methodName) {
|
|
27
|
+
if (methodName) {
|
|
28
|
+
return MetaHelper.get(VALIDATE_META, target[methodName]);
|
|
29
|
+
}
|
|
30
|
+
return MetaHelper.get(VALIDATE_META, target);
|
|
31
|
+
}
|
|
32
|
+
__name(getValidationConfig, "getValidationConfig");
|
|
33
|
+
|
|
34
|
+
// src/ValidationPlugin.ts
|
|
35
|
+
import { plugin } from "najm-core";
|
|
36
|
+
|
|
37
|
+
// src/ValidationService.ts
|
|
38
|
+
import { LoggerService, ScannerService, Scan, ScanType, INJECTION_TYPES, Err } from "najm-core";
|
|
39
|
+
import { Container, DI, Inject, Meta, Service } from "najm-core";
|
|
40
|
+
import { CONTEXT, REQUEST, PARSER } from "najm-core";
|
|
41
|
+
var __decorate = function(decorators, target, key, desc) {
|
|
42
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
43
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
44
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
45
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
46
|
+
};
|
|
47
|
+
var __metadata = function(k, v) {
|
|
48
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
49
|
+
};
|
|
50
|
+
var _a;
|
|
51
|
+
var _b;
|
|
52
|
+
var _c;
|
|
53
|
+
var ValidationService = class ValidationService2 {
|
|
54
|
+
static {
|
|
55
|
+
__name(this, "ValidationService");
|
|
56
|
+
}
|
|
57
|
+
container;
|
|
58
|
+
scanner;
|
|
59
|
+
config;
|
|
60
|
+
log;
|
|
61
|
+
validationCount = 0;
|
|
62
|
+
defaultErrorStatus = 400;
|
|
63
|
+
defaultStripUnknown = false;
|
|
64
|
+
defaultErrorFormatter;
|
|
65
|
+
async scan() {
|
|
66
|
+
this.validationCount = 0;
|
|
67
|
+
if (this.config?.enabled === false) {
|
|
68
|
+
this.log.info("Validation plugin disabled");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
this.scanner.scan(ScanType.CONTROLLER, {
|
|
72
|
+
onMethod: /* @__PURE__ */ __name((controller, methodName) => {
|
|
73
|
+
const validationConfig = getValidationConfig(controller.prototype, methodName);
|
|
74
|
+
if (validationConfig) {
|
|
75
|
+
this.container.setInjection({
|
|
76
|
+
type: INJECTION_TYPES.MIDDLEWARE,
|
|
77
|
+
target: controller,
|
|
78
|
+
methodName,
|
|
79
|
+
handler: this.createValidationMiddleware(validationConfig),
|
|
80
|
+
order: 45,
|
|
81
|
+
source: "validation"
|
|
82
|
+
});
|
|
83
|
+
this.validationCount++;
|
|
84
|
+
}
|
|
85
|
+
}, "onMethod")
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
async configure() {
|
|
89
|
+
if (this.config) {
|
|
90
|
+
this.defaultErrorStatus = this.config.errorStatus ?? 400;
|
|
91
|
+
this.defaultStripUnknown = this.config.stripUnknown ?? false;
|
|
92
|
+
this.defaultErrorFormatter = this.config.errorFormatter;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async activate() {
|
|
96
|
+
}
|
|
97
|
+
async onReady() {
|
|
98
|
+
if (this.validationCount > 0) {
|
|
99
|
+
this.log.info(`Validation: ${this.validationCount} route(s) configured`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Create validation middleware for a specific route
|
|
104
|
+
* Note: ctx param required by Hono but we use ALS internally
|
|
105
|
+
*/
|
|
106
|
+
createValidationMiddleware(config) {
|
|
107
|
+
return async (_ctx, next) => {
|
|
108
|
+
const targets = ["body", "params", "query", "headers"];
|
|
109
|
+
for (const target of targets) {
|
|
110
|
+
const schema = config[target];
|
|
111
|
+
if (schema) {
|
|
112
|
+
await this.validateTarget(target, schema, config);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return next();
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Validate a specific request target using ALS
|
|
120
|
+
*/
|
|
121
|
+
async validateTarget(target, schema, config) {
|
|
122
|
+
const data = await this.extractData(target);
|
|
123
|
+
const shouldStrip = config.stripUnknown ?? this.defaultStripUnknown;
|
|
124
|
+
try {
|
|
125
|
+
const finalSchema = shouldStrip && typeof schema.strip === "function" ? schema.strip() : schema;
|
|
126
|
+
const validatedData = finalSchema.parse(data);
|
|
127
|
+
const tokenMap = {
|
|
128
|
+
body: VALIDATED_BODY,
|
|
129
|
+
params: VALIDATED_PARAMS,
|
|
130
|
+
query: VALIDATED_QUERY,
|
|
131
|
+
headers: VALIDATED_HEADERS
|
|
132
|
+
};
|
|
133
|
+
this.container.set(tokenMap[target], validatedData);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
if (this.isZodErrorLike(error)) {
|
|
136
|
+
this.throwValidationError(error, target, config);
|
|
137
|
+
}
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
isZodErrorLike(error) {
|
|
142
|
+
if (!error || typeof error !== "object")
|
|
143
|
+
return false;
|
|
144
|
+
const issues = error.issues;
|
|
145
|
+
return Array.isArray(issues);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Extract data from ALS instead of ctx
|
|
149
|
+
*/
|
|
150
|
+
async extractData(target) {
|
|
151
|
+
const request = this.container.get(REQUEST);
|
|
152
|
+
const parser = this.container.get(PARSER);
|
|
153
|
+
const context = this.container.get(CONTEXT);
|
|
154
|
+
switch (target) {
|
|
155
|
+
case "body":
|
|
156
|
+
return parser.parseBody();
|
|
157
|
+
case "params":
|
|
158
|
+
return context.req.param();
|
|
159
|
+
// or request.params if HRequest has it parsed
|
|
160
|
+
case "query":
|
|
161
|
+
return request.query;
|
|
162
|
+
case "headers":
|
|
163
|
+
return request.headers;
|
|
164
|
+
default:
|
|
165
|
+
return {};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
throwValidationError(error, target, config) {
|
|
169
|
+
const errorStatus = config.errorStatus ?? this.defaultErrorStatus;
|
|
170
|
+
const formatter = config.errorFormatter ?? this.defaultErrorFormatter;
|
|
171
|
+
if (formatter) {
|
|
172
|
+
try {
|
|
173
|
+
const customResponse = formatter(error, target);
|
|
174
|
+
const customError = Err.createFromZod(error, target, errorStatus);
|
|
175
|
+
customError.toJSON = () => customResponse;
|
|
176
|
+
throw customError;
|
|
177
|
+
} catch (formatterError) {
|
|
178
|
+
if (formatterError instanceof Error && formatterError.message.includes("Cannot read")) {
|
|
179
|
+
Err.fromZod(error, target, errorStatus);
|
|
180
|
+
}
|
|
181
|
+
throw formatterError;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
Err.fromZod(error, target, errorStatus);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
__decorate([
|
|
188
|
+
DI(),
|
|
189
|
+
__metadata("design:type", typeof (_a = typeof Container !== "undefined" && Container) === "function" ? _a : Object)
|
|
190
|
+
], ValidationService.prototype, "container", void 0);
|
|
191
|
+
__decorate([
|
|
192
|
+
Scan(),
|
|
193
|
+
__metadata("design:type", typeof (_b = typeof ScannerService !== "undefined" && ScannerService) === "function" ? _b : Object)
|
|
194
|
+
], ValidationService.prototype, "scanner", void 0);
|
|
195
|
+
__decorate([
|
|
196
|
+
Inject(VALIDATION_CONFIG),
|
|
197
|
+
__metadata("design:type", Object)
|
|
198
|
+
], ValidationService.prototype, "config", void 0);
|
|
199
|
+
__decorate([
|
|
200
|
+
Inject(LoggerService),
|
|
201
|
+
__metadata("design:type", typeof (_c = typeof LoggerService !== "undefined" && LoggerService) === "function" ? _c : Object)
|
|
202
|
+
], ValidationService.prototype, "log", void 0);
|
|
203
|
+
ValidationService = __decorate([
|
|
204
|
+
Service(),
|
|
205
|
+
Meta({ layer: "plugin", order: 45 })
|
|
206
|
+
], ValidationService);
|
|
207
|
+
|
|
208
|
+
// src/ValidationPlugin.ts
|
|
209
|
+
var validation = /* @__PURE__ */ __name((config = {}) => plugin("validation").version("0.0.1").services(ValidationService).config(VALIDATION_CONFIG, config).build(), "validation");
|
|
210
|
+
export {
|
|
211
|
+
VALIDATED_BODY,
|
|
212
|
+
VALIDATED_HEADERS,
|
|
213
|
+
VALIDATED_PARAMS,
|
|
214
|
+
VALIDATED_QUERY,
|
|
215
|
+
VALIDATE_META,
|
|
216
|
+
VALIDATION_CONFIG,
|
|
217
|
+
Validate,
|
|
218
|
+
ValidationService,
|
|
219
|
+
getValidationConfig,
|
|
220
|
+
validation
|
|
221
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "najm-validation",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Request validation plugin for Najm framework using Zod schemas",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"bun": "./src/index.ts",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./*": {
|
|
19
|
+
"bun": "./src/*.ts",
|
|
20
|
+
"types": "./src/*.ts",
|
|
21
|
+
"import": "./src/*.ts",
|
|
22
|
+
"default": "./src/*.ts"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup",
|
|
27
|
+
"test": "bun test",
|
|
28
|
+
"test:watch": "bun test --watch",
|
|
29
|
+
"clean": "rimraf dist tsconfig.tsbuildinfo",
|
|
30
|
+
"typecheck:test": "tsc -p tsconfig.test.json"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"najm-core": "^0.1.1"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"hono": "^4.0.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"typescript": "^5.7.3",
|
|
40
|
+
"rimraf": "^6.0.1",
|
|
41
|
+
"tsup": "^8.0.0"
|
|
42
|
+
}
|
|
43
|
+
}
|