detype 0.6.3 → 1.0.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/README.md +8 -3
- package/dist/cli.js +71 -30
- package/dist/index.d.ts +1 -1
- package/dist/index.js +48 -8
- package/package.json +18 -18
package/README.md
CHANGED
|
@@ -132,17 +132,17 @@ function transformFile(
|
|
|
132
132
|
): Promise<void>;
|
|
133
133
|
|
|
134
134
|
// Remove magic comments without performing the TS to JS transform
|
|
135
|
-
export function removeMagicComments(
|
|
135
|
+
export async function removeMagicComments(
|
|
136
136
|
// Source code
|
|
137
137
|
code: string,
|
|
138
138
|
// File name for the source
|
|
139
139
|
fileName: string,
|
|
140
140
|
// Options to pass to prettier
|
|
141
141
|
prettierOptions?: PrettierOptions | null,
|
|
142
|
-
): string
|
|
142
|
+
): Promise<string>;
|
|
143
143
|
|
|
144
144
|
// Remove magic comments from the input file and write the output to another file
|
|
145
|
-
export function removeMagicCommentsFromFile(
|
|
145
|
+
export async function removeMagicCommentsFromFile(
|
|
146
146
|
inputFileName: string,
|
|
147
147
|
outputFileName: string,
|
|
148
148
|
): Promise<void>;
|
|
@@ -150,6 +150,11 @@ export function removeMagicCommentsFromFile(
|
|
|
150
150
|
|
|
151
151
|
## Change log
|
|
152
152
|
|
|
153
|
+
### 1.0
|
|
154
|
+
|
|
155
|
+
- BREAKING CHANGE: `removeMagicComments` is now async due to Prettier's API change
|
|
156
|
+
- feat: support transform defineProps's and defineEmits's types to parameters ([PR by Dunqing](https://github.com/cyco130/detype/pull/11))
|
|
157
|
+
|
|
153
158
|
### 0.6
|
|
154
159
|
|
|
155
160
|
- feature: Option to remove @ts-ignore and @ts-expect-error comments
|
package/dist/cli.js
CHANGED
|
@@ -33,15 +33,36 @@ var import_node_fs = __toESM(require("fs"));
|
|
|
33
33
|
var import_core = require("@babel/core");
|
|
34
34
|
var import_prettier = require("prettier");
|
|
35
35
|
var import_compiler_sfc = require("@vuedx/compiler-sfc");
|
|
36
|
+
var import_compiler_sfc2 = require("@vue/compiler-sfc");
|
|
36
37
|
var import_template_ast_types = require("@vuedx/template-ast-types");
|
|
37
38
|
var import_preset_typescript = __toESM(require("@babel/preset-typescript"));
|
|
38
39
|
var import_string_prototype = require("string.prototype.replaceall");
|
|
39
40
|
(0, import_string_prototype.shim)();
|
|
41
|
+
function getDefinePropsObject(content) {
|
|
42
|
+
const matched = /\sprops:\s*\{/m.exec(content);
|
|
43
|
+
if (matched) {
|
|
44
|
+
const startContentIndex = matched.index + matched[0].length - 1;
|
|
45
|
+
let leftBracketCount = 1;
|
|
46
|
+
let endContentIndex = startContentIndex + 1;
|
|
47
|
+
while (leftBracketCount) {
|
|
48
|
+
if (content.charAt(endContentIndex) === "{") {
|
|
49
|
+
leftBracketCount++;
|
|
50
|
+
} else if (content.charAt(endContentIndex) === "}") {
|
|
51
|
+
leftBracketCount--;
|
|
52
|
+
}
|
|
53
|
+
endContentIndex++;
|
|
54
|
+
}
|
|
55
|
+
return content.substring(startContentIndex, endContentIndex);
|
|
56
|
+
}
|
|
57
|
+
return "";
|
|
58
|
+
}
|
|
40
59
|
async function transform(code, fileName, options = {}) {
|
|
41
|
-
var _a, _b, _c, _d;
|
|
60
|
+
var _a, _b, _c, _d, _e;
|
|
42
61
|
const { prettierOptions, ...removeTypeOptions } = options;
|
|
43
62
|
const originalCode = code;
|
|
44
63
|
const originalFileName = fileName;
|
|
64
|
+
let propsContent = "";
|
|
65
|
+
let emitsContent = "";
|
|
45
66
|
code = code.replaceAll("\r\n", "\n");
|
|
46
67
|
if (fileName.endsWith(".vue")) {
|
|
47
68
|
const parsedVue = (0, import_compiler_sfc.parse)(code);
|
|
@@ -49,6 +70,19 @@ async function transform(code, fileName, options = {}) {
|
|
|
49
70
|
return originalCode;
|
|
50
71
|
}
|
|
51
72
|
let { script: script1, scriptSetup: script2 } = parsedVue.descriptor;
|
|
73
|
+
const isContainsDefinePropsType = script2 == null ? void 0 : script2.content.match(/defineProps\s*</m);
|
|
74
|
+
const isContainsDefineEmitType = script2 == null ? void 0 : script2.content.match(/defineEmits\s*</m);
|
|
75
|
+
if (isContainsDefinePropsType || isContainsDefineEmitType) {
|
|
76
|
+
const { content } = (0, import_compiler_sfc2.compileScript)(parsedVue.descriptor, {
|
|
77
|
+
id: "xxxxxxx"
|
|
78
|
+
});
|
|
79
|
+
if (isContainsDefinePropsType) {
|
|
80
|
+
propsContent = getDefinePropsObject(content);
|
|
81
|
+
}
|
|
82
|
+
if (isContainsDefineEmitType) {
|
|
83
|
+
emitsContent = ((_c = content.match(/\semits:\s(\[.*\]?)/m)) == null ? void 0 : _c[1]) || "";
|
|
84
|
+
}
|
|
85
|
+
}
|
|
52
86
|
if (script1 && script2 && script1.loc.start.offset < script2.loc.start.offset) {
|
|
53
87
|
[script2, script1] = [script1, script2];
|
|
54
88
|
}
|
|
@@ -56,20 +90,26 @@ async function transform(code, fileName, options = {}) {
|
|
|
56
90
|
code,
|
|
57
91
|
fileName,
|
|
58
92
|
script1,
|
|
59
|
-
(
|
|
93
|
+
(_d = parsedVue.descriptor.template) == null ? void 0 : _d.ast,
|
|
60
94
|
removeTypeOptions
|
|
61
95
|
);
|
|
62
96
|
code = await removeTypesFromVueSfcScript(
|
|
63
97
|
code,
|
|
64
98
|
fileName,
|
|
65
99
|
script2,
|
|
66
|
-
(
|
|
100
|
+
(_e = parsedVue.descriptor.template) == null ? void 0 : _e.ast,
|
|
67
101
|
removeTypeOptions
|
|
68
102
|
);
|
|
69
103
|
} else {
|
|
70
104
|
code = await removeTypes(code, fileName, removeTypeOptions);
|
|
71
105
|
}
|
|
72
|
-
|
|
106
|
+
if (propsContent) {
|
|
107
|
+
code = code.replace("defineProps(", (str) => `${str}${propsContent}`);
|
|
108
|
+
}
|
|
109
|
+
if (emitsContent) {
|
|
110
|
+
code = code.replace("defineEmits(", (str) => `${str}${emitsContent}`);
|
|
111
|
+
}
|
|
112
|
+
code = await (0, import_prettier.format)(code, {
|
|
73
113
|
...prettierOptions,
|
|
74
114
|
filepath: originalFileName
|
|
75
115
|
});
|
|
@@ -138,9 +178,9 @@ async function removeTypesFromVueSfcScript(code, fileName, script, templateAst,
|
|
|
138
178
|
(0, import_template_ast_types.traverse)(templateAst, {
|
|
139
179
|
enter(node) {
|
|
140
180
|
if ((0, import_template_ast_types.isSimpleExpressionNode)(node) && !node.isStatic) {
|
|
141
|
-
expressions.add(node.content);
|
|
181
|
+
expressions.add(`[${node.content}]`);
|
|
142
182
|
} else if ((0, import_template_ast_types.isComponentNode)(node)) {
|
|
143
|
-
expressions.add(node.tag);
|
|
183
|
+
expressions.add(`[${node.tag}]`);
|
|
144
184
|
}
|
|
145
185
|
}
|
|
146
186
|
});
|
|
@@ -185,7 +225,7 @@ function processMagicComments(input) {
|
|
|
185
225
|
}
|
|
186
226
|
return input;
|
|
187
227
|
}
|
|
188
|
-
function removeMagicComments(code, fileName, prettierOptions) {
|
|
228
|
+
async function removeMagicComments(code, fileName, prettierOptions) {
|
|
189
229
|
const REPLACE_COMMENT = "// @detype: replace\n";
|
|
190
230
|
const WITH_COMMENT = "// @detype: with\n";
|
|
191
231
|
const END_COMMENT = "// @detype: end\n";
|
|
@@ -207,7 +247,7 @@ function removeMagicComments(code, fileName, prettierOptions) {
|
|
|
207
247
|
start = code.indexOf(REPLACE_COMMENT, before.length + keptText.length);
|
|
208
248
|
startEnd = start + REPLACE_COMMENT.length;
|
|
209
249
|
}
|
|
210
|
-
code = (0, import_prettier.format)(code, {
|
|
250
|
+
code = await (0, import_prettier.format)(code, {
|
|
211
251
|
...prettierOptions,
|
|
212
252
|
filepath: fileName
|
|
213
253
|
});
|
|
@@ -239,7 +279,7 @@ var import_fast_glob = __toESM(require("fast-glob"));
|
|
|
239
279
|
// package.json
|
|
240
280
|
var package_default = {
|
|
241
281
|
name: "detype",
|
|
242
|
-
version: "0.
|
|
282
|
+
version: "1.0.1",
|
|
243
283
|
description: "Removes TypeScript type annotations but keeps the formatting",
|
|
244
284
|
main: "dist/index.js",
|
|
245
285
|
bin: "detype.js",
|
|
@@ -263,28 +303,28 @@ var package_default = {
|
|
|
263
303
|
"index.d.ts"
|
|
264
304
|
],
|
|
265
305
|
dependencies: {
|
|
266
|
-
"@babel/core": "^7.
|
|
267
|
-
"@babel/preset-typescript": "^7.
|
|
268
|
-
"@vue/compiler-dom": "^3.
|
|
306
|
+
"@babel/core": "^7.23.7",
|
|
307
|
+
"@babel/preset-typescript": "^7.23.3",
|
|
308
|
+
"@vue/compiler-dom": "^3.4.13",
|
|
309
|
+
"@vue/compiler-sfc": "^3.4.13",
|
|
269
310
|
"@vuedx/compiler-sfc": "0.7.1",
|
|
270
311
|
"@vuedx/template-ast-types": "0.7.1",
|
|
271
|
-
"fast-glob": "^3.2
|
|
272
|
-
prettier: "^2.
|
|
273
|
-
"string.prototype.replaceall": "^1.0.
|
|
312
|
+
"fast-glob": "^3.3.2",
|
|
313
|
+
prettier: "^3.2.2",
|
|
314
|
+
"string.prototype.replaceall": "^1.0.8"
|
|
274
315
|
},
|
|
275
316
|
devDependencies: {
|
|
276
|
-
"@babel/traverse": "^7.
|
|
277
|
-
"@cyco130/eslint-config": "^3.
|
|
278
|
-
"@types/babel__core": "^7.20.
|
|
279
|
-
"@types/babel__traverse": "^7.
|
|
280
|
-
"@types/node": "
|
|
281
|
-
|
|
282
|
-
eslint: "^8.37.0",
|
|
317
|
+
"@babel/traverse": "^7.23.7",
|
|
318
|
+
"@cyco130/eslint-config": "^3.6.1",
|
|
319
|
+
"@types/babel__core": "^7.20.5",
|
|
320
|
+
"@types/babel__traverse": "^7.20.5",
|
|
321
|
+
"@types/node": "20.11.1",
|
|
322
|
+
eslint: "^8.56.0",
|
|
283
323
|
"npm-run-all": "^4.1.5",
|
|
284
|
-
rimraf: "^
|
|
285
|
-
tsup: "^
|
|
286
|
-
typescript: "^5.
|
|
287
|
-
vitest: "
|
|
324
|
+
rimraf: "^5.0.5",
|
|
325
|
+
tsup: "^8.0.1",
|
|
326
|
+
typescript: "^5.3.3",
|
|
327
|
+
vitest: "1.2.0"
|
|
288
328
|
},
|
|
289
329
|
repository: {
|
|
290
330
|
type: "git",
|
|
@@ -353,9 +393,7 @@ async function cli(...args2) {
|
|
|
353
393
|
printUsage();
|
|
354
394
|
return false;
|
|
355
395
|
}
|
|
356
|
-
const files = (await (0, import_fast_glob.default)(unixify(input + "/**/*.{ts,tsx,vue}"))).filter(
|
|
357
|
-
(file) => !file.endsWith(".d.ts")
|
|
358
|
-
);
|
|
396
|
+
const files = (await (0, import_fast_glob.default)(unixify(input + "/**/*.{ts,tsx,vue}"))).filter((file) => !file.endsWith(".d.ts"));
|
|
359
397
|
const dirs = [...new Set(files.map((file) => import_node_path.default.dirname(file)))].sort();
|
|
360
398
|
await mkdir(import_node_path.default.normalize(output), { recursive: true });
|
|
361
399
|
for (const dir of dirs) {
|
|
@@ -461,4 +499,7 @@ function unixify(name) {
|
|
|
461
499
|
|
|
462
500
|
// src/cli.ts
|
|
463
501
|
var args = process.argv.slice(2);
|
|
464
|
-
cli(...args).then((success) => process.exit(success ? 0 : 1))
|
|
502
|
+
cli(...args).then((success) => process.exit(success ? 0 : 1)).catch((error) => {
|
|
503
|
+
console.error(error);
|
|
504
|
+
process.exit(1);
|
|
505
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ declare function transform(code: string, fileName: string, options?: TransformOp
|
|
|
25
25
|
* @param fileName File name for the source
|
|
26
26
|
* @param prettierOptions Options to pass to prettier
|
|
27
27
|
*/
|
|
28
|
-
declare function removeMagicComments(code: string, fileName: string, prettierOptions?: Options | null): string
|
|
28
|
+
declare function removeMagicComments(code: string, fileName: string, prettierOptions?: Options | null): Promise<string>;
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Transform the input file and write the output to another file
|
package/dist/index.js
CHANGED
|
@@ -41,15 +41,36 @@ module.exports = __toCommonJS(src_exports);
|
|
|
41
41
|
var import_core = require("@babel/core");
|
|
42
42
|
var import_prettier = require("prettier");
|
|
43
43
|
var import_compiler_sfc = require("@vuedx/compiler-sfc");
|
|
44
|
+
var import_compiler_sfc2 = require("@vue/compiler-sfc");
|
|
44
45
|
var import_template_ast_types = require("@vuedx/template-ast-types");
|
|
45
46
|
var import_preset_typescript = __toESM(require("@babel/preset-typescript"));
|
|
46
47
|
var import_string_prototype = require("string.prototype.replaceall");
|
|
47
48
|
(0, import_string_prototype.shim)();
|
|
49
|
+
function getDefinePropsObject(content) {
|
|
50
|
+
const matched = /\sprops:\s*\{/m.exec(content);
|
|
51
|
+
if (matched) {
|
|
52
|
+
const startContentIndex = matched.index + matched[0].length - 1;
|
|
53
|
+
let leftBracketCount = 1;
|
|
54
|
+
let endContentIndex = startContentIndex + 1;
|
|
55
|
+
while (leftBracketCount) {
|
|
56
|
+
if (content.charAt(endContentIndex) === "{") {
|
|
57
|
+
leftBracketCount++;
|
|
58
|
+
} else if (content.charAt(endContentIndex) === "}") {
|
|
59
|
+
leftBracketCount--;
|
|
60
|
+
}
|
|
61
|
+
endContentIndex++;
|
|
62
|
+
}
|
|
63
|
+
return content.substring(startContentIndex, endContentIndex);
|
|
64
|
+
}
|
|
65
|
+
return "";
|
|
66
|
+
}
|
|
48
67
|
async function transform(code, fileName, options = {}) {
|
|
49
|
-
var _a, _b, _c, _d;
|
|
68
|
+
var _a, _b, _c, _d, _e;
|
|
50
69
|
const { prettierOptions, ...removeTypeOptions } = options;
|
|
51
70
|
const originalCode = code;
|
|
52
71
|
const originalFileName = fileName;
|
|
72
|
+
let propsContent = "";
|
|
73
|
+
let emitsContent = "";
|
|
53
74
|
code = code.replaceAll("\r\n", "\n");
|
|
54
75
|
if (fileName.endsWith(".vue")) {
|
|
55
76
|
const parsedVue = (0, import_compiler_sfc.parse)(code);
|
|
@@ -57,6 +78,19 @@ async function transform(code, fileName, options = {}) {
|
|
|
57
78
|
return originalCode;
|
|
58
79
|
}
|
|
59
80
|
let { script: script1, scriptSetup: script2 } = parsedVue.descriptor;
|
|
81
|
+
const isContainsDefinePropsType = script2 == null ? void 0 : script2.content.match(/defineProps\s*</m);
|
|
82
|
+
const isContainsDefineEmitType = script2 == null ? void 0 : script2.content.match(/defineEmits\s*</m);
|
|
83
|
+
if (isContainsDefinePropsType || isContainsDefineEmitType) {
|
|
84
|
+
const { content } = (0, import_compiler_sfc2.compileScript)(parsedVue.descriptor, {
|
|
85
|
+
id: "xxxxxxx"
|
|
86
|
+
});
|
|
87
|
+
if (isContainsDefinePropsType) {
|
|
88
|
+
propsContent = getDefinePropsObject(content);
|
|
89
|
+
}
|
|
90
|
+
if (isContainsDefineEmitType) {
|
|
91
|
+
emitsContent = ((_c = content.match(/\semits:\s(\[.*\]?)/m)) == null ? void 0 : _c[1]) || "";
|
|
92
|
+
}
|
|
93
|
+
}
|
|
60
94
|
if (script1 && script2 && script1.loc.start.offset < script2.loc.start.offset) {
|
|
61
95
|
[script2, script1] = [script1, script2];
|
|
62
96
|
}
|
|
@@ -64,20 +98,26 @@ async function transform(code, fileName, options = {}) {
|
|
|
64
98
|
code,
|
|
65
99
|
fileName,
|
|
66
100
|
script1,
|
|
67
|
-
(
|
|
101
|
+
(_d = parsedVue.descriptor.template) == null ? void 0 : _d.ast,
|
|
68
102
|
removeTypeOptions
|
|
69
103
|
);
|
|
70
104
|
code = await removeTypesFromVueSfcScript(
|
|
71
105
|
code,
|
|
72
106
|
fileName,
|
|
73
107
|
script2,
|
|
74
|
-
(
|
|
108
|
+
(_e = parsedVue.descriptor.template) == null ? void 0 : _e.ast,
|
|
75
109
|
removeTypeOptions
|
|
76
110
|
);
|
|
77
111
|
} else {
|
|
78
112
|
code = await removeTypes(code, fileName, removeTypeOptions);
|
|
79
113
|
}
|
|
80
|
-
|
|
114
|
+
if (propsContent) {
|
|
115
|
+
code = code.replace("defineProps(", (str) => `${str}${propsContent}`);
|
|
116
|
+
}
|
|
117
|
+
if (emitsContent) {
|
|
118
|
+
code = code.replace("defineEmits(", (str) => `${str}${emitsContent}`);
|
|
119
|
+
}
|
|
120
|
+
code = await (0, import_prettier.format)(code, {
|
|
81
121
|
...prettierOptions,
|
|
82
122
|
filepath: originalFileName
|
|
83
123
|
});
|
|
@@ -146,9 +186,9 @@ async function removeTypesFromVueSfcScript(code, fileName, script, templateAst,
|
|
|
146
186
|
(0, import_template_ast_types.traverse)(templateAst, {
|
|
147
187
|
enter(node) {
|
|
148
188
|
if ((0, import_template_ast_types.isSimpleExpressionNode)(node) && !node.isStatic) {
|
|
149
|
-
expressions.add(node.content);
|
|
189
|
+
expressions.add(`[${node.content}]`);
|
|
150
190
|
} else if ((0, import_template_ast_types.isComponentNode)(node)) {
|
|
151
|
-
expressions.add(node.tag);
|
|
191
|
+
expressions.add(`[${node.tag}]`);
|
|
152
192
|
}
|
|
153
193
|
}
|
|
154
194
|
});
|
|
@@ -193,7 +233,7 @@ function processMagicComments(input) {
|
|
|
193
233
|
}
|
|
194
234
|
return input;
|
|
195
235
|
}
|
|
196
|
-
function removeMagicComments(code, fileName, prettierOptions) {
|
|
236
|
+
async function removeMagicComments(code, fileName, prettierOptions) {
|
|
197
237
|
const REPLACE_COMMENT = "// @detype: replace\n";
|
|
198
238
|
const WITH_COMMENT = "// @detype: with\n";
|
|
199
239
|
const END_COMMENT = "// @detype: end\n";
|
|
@@ -215,7 +255,7 @@ function removeMagicComments(code, fileName, prettierOptions) {
|
|
|
215
255
|
start = code.indexOf(REPLACE_COMMENT, before.length + keptText.length);
|
|
216
256
|
startEnd = start + REPLACE_COMMENT.length;
|
|
217
257
|
}
|
|
218
|
-
code = (0, import_prettier.format)(code, {
|
|
258
|
+
code = await (0, import_prettier.format)(code, {
|
|
219
259
|
...prettierOptions,
|
|
220
260
|
filepath: fileName
|
|
221
261
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "detype",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Removes TypeScript type annotations but keeps the formatting",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": "detype.js",
|
|
@@ -12,28 +12,28 @@
|
|
|
12
12
|
"index.d.ts"
|
|
13
13
|
],
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@babel/core": "^7.
|
|
16
|
-
"@babel/preset-typescript": "^7.
|
|
17
|
-
"@vue/compiler-dom": "^3.
|
|
15
|
+
"@babel/core": "^7.23.7",
|
|
16
|
+
"@babel/preset-typescript": "^7.23.3",
|
|
17
|
+
"@vue/compiler-dom": "^3.4.13",
|
|
18
|
+
"@vue/compiler-sfc": "^3.4.13",
|
|
18
19
|
"@vuedx/compiler-sfc": "0.7.1",
|
|
19
20
|
"@vuedx/template-ast-types": "0.7.1",
|
|
20
|
-
"fast-glob": "^3.2
|
|
21
|
-
"prettier": "^2.
|
|
22
|
-
"string.prototype.replaceall": "^1.0.
|
|
21
|
+
"fast-glob": "^3.3.2",
|
|
22
|
+
"prettier": "^3.2.2",
|
|
23
|
+
"string.prototype.replaceall": "^1.0.8"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
|
-
"@babel/traverse": "^7.
|
|
26
|
-
"@cyco130/eslint-config": "^3.
|
|
27
|
-
"@types/babel__core": "^7.20.
|
|
28
|
-
"@types/babel__traverse": "^7.
|
|
29
|
-
"@types/node": "
|
|
30
|
-
"
|
|
31
|
-
"eslint": "^8.37.0",
|
|
26
|
+
"@babel/traverse": "^7.23.7",
|
|
27
|
+
"@cyco130/eslint-config": "^3.6.1",
|
|
28
|
+
"@types/babel__core": "^7.20.5",
|
|
29
|
+
"@types/babel__traverse": "^7.20.5",
|
|
30
|
+
"@types/node": "20.11.1",
|
|
31
|
+
"eslint": "^8.56.0",
|
|
32
32
|
"npm-run-all": "^4.1.5",
|
|
33
|
-
"rimraf": "^
|
|
34
|
-
"tsup": "^
|
|
35
|
-
"typescript": "^5.
|
|
36
|
-
"vitest": "
|
|
33
|
+
"rimraf": "^5.0.5",
|
|
34
|
+
"tsup": "^8.0.1",
|
|
35
|
+
"typescript": "^5.3.3",
|
|
36
|
+
"vitest": "1.2.0"
|
|
37
37
|
},
|
|
38
38
|
"repository": {
|
|
39
39
|
"type": "git",
|