@meistrari/vault-sdk 1.0.1 → 1.2.0
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.cjs +142 -70
- package/dist/index.d.cts +77 -20
- package/dist/index.d.mts +77 -20
- package/dist/index.d.ts +77 -20
- package/dist/index.mjs +142 -70
- package/package.json +14 -11
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,35 @@
|
|
|
1
1
|
import { GetUploadUrlResponseV2, GetDownloadUrlResponse } from '@meistrari/vault-shared/schemas';
|
|
2
|
+
import { fileTypeFromBlob } from 'file-type';
|
|
3
|
+
import { lookup } from 'mime-types';
|
|
4
|
+
|
|
5
|
+
var __defProp$1 = Object.defineProperty;
|
|
6
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7
|
+
var __publicField$1 = (obj, key, value) => {
|
|
8
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
9
|
+
return value;
|
|
10
|
+
};
|
|
11
|
+
class DataTokenAuthStrategy {
|
|
12
|
+
constructor(dataToken) {
|
|
13
|
+
__publicField$1(this, "dataToken");
|
|
14
|
+
this.dataToken = dataToken;
|
|
15
|
+
}
|
|
16
|
+
getHeaders() {
|
|
17
|
+
return new Headers({
|
|
18
|
+
"x-data-token": this.dataToken
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
class APIKeyAuthStrategy {
|
|
23
|
+
constructor(apiKey) {
|
|
24
|
+
__publicField$1(this, "apiKey");
|
|
25
|
+
this.apiKey = apiKey;
|
|
26
|
+
}
|
|
27
|
+
getHeaders() {
|
|
28
|
+
return new Headers({
|
|
29
|
+
Authorization: this.apiKey
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
2
33
|
|
|
3
34
|
class FetchError extends Error {
|
|
4
35
|
constructor(message, url, method, response) {
|
|
@@ -32,11 +63,30 @@ async function getFileHash(blob) {
|
|
|
32
63
|
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
33
64
|
return hashHex;
|
|
34
65
|
}
|
|
66
|
+
async function detectFileMimeType(blob) {
|
|
67
|
+
const result = await fileTypeFromBlob(blob).catch(() => void 0);
|
|
68
|
+
if (result?.mime) {
|
|
69
|
+
return result.mime;
|
|
70
|
+
}
|
|
71
|
+
if ("name" in blob && typeof blob.name === "string") {
|
|
72
|
+
const extension = blob.name.split(".").pop()?.toLowerCase();
|
|
73
|
+
if (extension) {
|
|
74
|
+
const mimeType = lookup(`.${extension}`);
|
|
75
|
+
if (mimeType) {
|
|
76
|
+
return mimeType;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (blob instanceof Blob && blob.type) {
|
|
81
|
+
return blob.type;
|
|
82
|
+
}
|
|
83
|
+
return void 0;
|
|
84
|
+
}
|
|
35
85
|
|
|
36
|
-
var __defProp
|
|
37
|
-
var __defNormalProp
|
|
38
|
-
var __publicField
|
|
39
|
-
__defNormalProp
|
|
86
|
+
var __defProp = Object.defineProperty;
|
|
87
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
88
|
+
var __publicField = (obj, key, value) => {
|
|
89
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
40
90
|
return value;
|
|
41
91
|
};
|
|
42
92
|
const compatibilityDate = "2025-05-19";
|
|
@@ -65,13 +115,13 @@ class VaultFile {
|
|
|
65
115
|
* @param params.metadata - The metadata of the file
|
|
66
116
|
*/
|
|
67
117
|
constructor({ config, content, id, name, metadata }) {
|
|
68
|
-
__publicField
|
|
69
|
-
__publicField
|
|
70
|
-
__publicField
|
|
71
|
-
__publicField
|
|
72
|
-
__publicField
|
|
73
|
-
__publicField
|
|
74
|
-
__publicField
|
|
118
|
+
__publicField(this, "id");
|
|
119
|
+
__publicField(this, "name");
|
|
120
|
+
__publicField(this, "metadata");
|
|
121
|
+
__publicField(this, "config");
|
|
122
|
+
__publicField(this, "content");
|
|
123
|
+
__publicField(this, "lastDownloadUrl");
|
|
124
|
+
__publicField(this, "lastUploadUrl");
|
|
75
125
|
this.config = config;
|
|
76
126
|
this.content = content;
|
|
77
127
|
this.id = id;
|
|
@@ -93,37 +143,46 @@ class VaultFile {
|
|
|
93
143
|
* @param params.method - The method to use for the fetch
|
|
94
144
|
* @param params.path - The path to fetch
|
|
95
145
|
* @param params.body - The body of the request
|
|
146
|
+
* @param params.signal - The signal to abort the request
|
|
96
147
|
* @returns The response from the vault
|
|
97
148
|
* @throws {FetchError} If the fetch fails
|
|
98
149
|
*/
|
|
99
150
|
async _fetch(params) {
|
|
100
|
-
const { method, path, body } = params;
|
|
151
|
+
const { method, path, body, signal } = params;
|
|
101
152
|
const url = new URL(this.config.vaultUrl + path).toString();
|
|
102
153
|
const headers = new Headers(this.headers);
|
|
103
154
|
headers.set("x-compatibility-date", compatibilityDate);
|
|
104
155
|
const response = await wrappedFetch(url, {
|
|
105
156
|
method,
|
|
106
157
|
body,
|
|
107
|
-
headers
|
|
158
|
+
headers,
|
|
159
|
+
signal
|
|
108
160
|
});
|
|
109
161
|
const content = await response.json();
|
|
110
162
|
return content;
|
|
111
163
|
}
|
|
112
164
|
/**
|
|
113
165
|
* Creates a new file in the vault.
|
|
166
|
+
* @param metadata - The metadata for creating a file
|
|
167
|
+
* @param metadata.size - The size of the file
|
|
168
|
+
* @param metadata.mimeType - The mime type of the file
|
|
169
|
+
* @param options - The options for the request
|
|
170
|
+
* @param options.signal - The signal to abort the request
|
|
114
171
|
*
|
|
115
172
|
* @returns The metadata of the file
|
|
116
173
|
* @throws {Error} If the file ID is not set
|
|
117
174
|
* @throws {FetchError} If the metadata fetch fails
|
|
118
175
|
*/
|
|
119
|
-
async _createFile() {
|
|
176
|
+
async _createFile(metadata = {}, options) {
|
|
120
177
|
const response = await this._fetch({
|
|
121
178
|
method: "POST",
|
|
122
179
|
path: `/v2/files`,
|
|
123
180
|
body: JSON.stringify({
|
|
181
|
+
...metadata,
|
|
124
182
|
fileName: this.name,
|
|
125
183
|
sha256sum: this.id ?? this.metadata?.id ?? (this.content ? await getFileHash(this.content) : void 0)
|
|
126
|
-
})
|
|
184
|
+
}),
|
|
185
|
+
signal: options?.signal
|
|
127
186
|
}).then((data) => GetUploadUrlResponseV2.safeParse(data));
|
|
128
187
|
if (!response.success) {
|
|
129
188
|
throw new Error(`Invalid response from vault service. ${JSON.stringify(response.error)}`);
|
|
@@ -140,6 +199,9 @@ class VaultFile {
|
|
|
140
199
|
* @param params.reference - The reference to the file in the vault
|
|
141
200
|
* @param params.config - The configuration for the VaultFile
|
|
142
201
|
* @param params.download - Whether to download the file content (default: false)
|
|
202
|
+
* @param options - The options for the request
|
|
203
|
+
* @param options.signal - The signal to abort the request
|
|
204
|
+
*
|
|
143
205
|
* @returns A new VaultFile instance
|
|
144
206
|
*
|
|
145
207
|
* @example
|
|
@@ -169,13 +231,14 @@ class VaultFile {
|
|
|
169
231
|
* const content = vaultFile.content
|
|
170
232
|
* ```
|
|
171
233
|
*/
|
|
172
|
-
static async fromVaultReference(params) {
|
|
234
|
+
static async fromVaultReference(params, options) {
|
|
173
235
|
const { reference, config, download = false } = params;
|
|
174
236
|
const { vaultUrl, authStrategy } = config;
|
|
175
237
|
const id = removeVaultPrefix(reference);
|
|
176
238
|
const response = await wrappedFetch(`${vaultUrl}/v2/files/${id}`, {
|
|
177
239
|
method: "GET",
|
|
178
|
-
headers: authStrategy.getHeaders()
|
|
240
|
+
headers: authStrategy.getHeaders(),
|
|
241
|
+
signal: options?.signal
|
|
179
242
|
}).then((response2) => response2.json()).then((data) => GetDownloadUrlResponse.safeParse(data));
|
|
180
243
|
if (!response.success) {
|
|
181
244
|
throw new Error("Invalid response from vault service");
|
|
@@ -190,7 +253,7 @@ class VaultFile {
|
|
|
190
253
|
name: response.data.metadata?.originalFileName
|
|
191
254
|
};
|
|
192
255
|
if (download) {
|
|
193
|
-
await wrappedFetch(response.data.url, { method: "GET" }).then((response2) => response2.blob()).then((blob) => fileParams.content = blob);
|
|
256
|
+
await wrappedFetch(response.data.url, { method: "GET", signal: options?.signal }).then((response2) => response2.blob()).then((blob) => fileParams.content = blob);
|
|
194
257
|
}
|
|
195
258
|
return new VaultFile(fileParams);
|
|
196
259
|
}
|
|
@@ -202,6 +265,9 @@ class VaultFile {
|
|
|
202
265
|
* @param params.content - The content of the file
|
|
203
266
|
* @param params.config - The configuration for the VaultFile
|
|
204
267
|
* @param params.upload - Whether to upload the file (default: false)
|
|
268
|
+
* @param options - The options for the request
|
|
269
|
+
* @param options.signal - The signal to abort the request
|
|
270
|
+
*
|
|
205
271
|
* @returns A new VaultFile instance
|
|
206
272
|
*
|
|
207
273
|
* @example
|
|
@@ -234,10 +300,12 @@ class VaultFile {
|
|
|
234
300
|
* })
|
|
235
301
|
* ```
|
|
236
302
|
*/
|
|
237
|
-
static async fromContent(params) {
|
|
303
|
+
static async fromContent(params, options) {
|
|
238
304
|
const { name, content, config, upload = false } = params;
|
|
239
305
|
const { vaultUrl, authStrategy } = config;
|
|
240
306
|
const sha256sum = await getFileHash(content);
|
|
307
|
+
const mimeType = await detectFileMimeType(content);
|
|
308
|
+
const size = content.size;
|
|
241
309
|
const file = new VaultFile({
|
|
242
310
|
content,
|
|
243
311
|
config: {
|
|
@@ -247,22 +315,27 @@ class VaultFile {
|
|
|
247
315
|
id: sha256sum,
|
|
248
316
|
name
|
|
249
317
|
});
|
|
250
|
-
const createdFile = await file._createFile(
|
|
318
|
+
const createdFile = await file._createFile({
|
|
319
|
+
size,
|
|
320
|
+
mimeType
|
|
321
|
+
}, { signal: options?.signal });
|
|
251
322
|
if (upload) {
|
|
252
|
-
await file.upload(file.content, createdFile.uploadUrl);
|
|
323
|
+
await file.upload(file.content, createdFile.uploadUrl, { signal: options?.signal });
|
|
253
324
|
}
|
|
254
325
|
return file;
|
|
255
326
|
}
|
|
256
327
|
/**
|
|
257
328
|
* Populates the metadata of the file instance.
|
|
329
|
+
* @param options - The options for the request
|
|
330
|
+
* @param options.signal - The signal to abort the request
|
|
258
331
|
*
|
|
259
332
|
* @returns The file instance
|
|
260
333
|
* @throws {Error} If the file ID is not set
|
|
261
334
|
* @throws {FetchError} If the metadata fetch fails
|
|
262
335
|
*/
|
|
263
|
-
async populateMetadata() {
|
|
336
|
+
async populateMetadata(options) {
|
|
264
337
|
try {
|
|
265
|
-
this.metadata = await this.getFileMetadata();
|
|
338
|
+
this.metadata = await this.getFileMetadata({ signal: options?.signal });
|
|
266
339
|
this.name = this.metadata.originalFileName;
|
|
267
340
|
this.id = this.metadata.id;
|
|
268
341
|
return this;
|
|
@@ -284,29 +357,34 @@ class VaultFile {
|
|
|
284
357
|
}
|
|
285
358
|
/**
|
|
286
359
|
* Fetches the metadata of the file.
|
|
360
|
+
* @param options - The options for the request
|
|
361
|
+
* @param options.signal - The signal to abort the request
|
|
287
362
|
*
|
|
288
363
|
* @returns The metadata of the file
|
|
289
364
|
* @throws {Error} If the file ID is not set
|
|
290
365
|
* @throws {FetchError} If the metadata fetch fails
|
|
291
366
|
*/
|
|
292
|
-
async getFileMetadata() {
|
|
367
|
+
async getFileMetadata(options) {
|
|
293
368
|
if (!this.id) {
|
|
294
369
|
throw new Error("File ID is not set");
|
|
295
370
|
}
|
|
296
371
|
const response = await this._fetch({
|
|
297
372
|
method: "GET",
|
|
298
|
-
path: `/v2/files/${this.id}/metadata
|
|
373
|
+
path: `/v2/files/${this.id}/metadata`,
|
|
374
|
+
signal: options?.signal
|
|
299
375
|
});
|
|
300
376
|
return response;
|
|
301
377
|
}
|
|
302
378
|
/**
|
|
303
379
|
* Fetches a upload URL for the file.
|
|
380
|
+
* @param options - The options for the request
|
|
381
|
+
* @param options.signal - The signal to abort the request
|
|
304
382
|
*
|
|
305
383
|
* @returns The upload URL for the file
|
|
306
384
|
* @throws {Error} If the vault service returns an invalid response
|
|
307
385
|
* @throws {FetchError} If the upload URL fetch fails
|
|
308
386
|
*/
|
|
309
|
-
async getUploadUrl() {
|
|
387
|
+
async getUploadUrl(options) {
|
|
310
388
|
if (this.lastUploadUrl && this.lastUploadUrl.expiresAt > /* @__PURE__ */ new Date()) {
|
|
311
389
|
return this.lastUploadUrl.url;
|
|
312
390
|
}
|
|
@@ -320,7 +398,8 @@ class VaultFile {
|
|
|
320
398
|
}
|
|
321
399
|
const response = await this._fetch({
|
|
322
400
|
method: "PUT",
|
|
323
|
-
path: `/v2/files/${this.id}
|
|
401
|
+
path: `/v2/files/${this.id}`,
|
|
402
|
+
signal: options?.signal
|
|
324
403
|
}).then(GetUploadUrlResponseV2.safeParse);
|
|
325
404
|
if (!response.success) {
|
|
326
405
|
throw new Error(`Invalid response from vault service. ${JSON.stringify(response.error)}`);
|
|
@@ -330,13 +409,15 @@ class VaultFile {
|
|
|
330
409
|
}
|
|
331
410
|
/**
|
|
332
411
|
* Fetches a download URL for the file.
|
|
412
|
+
* @param options - The options for the request
|
|
413
|
+
* @param options.signal - The signal to abort the request
|
|
333
414
|
*
|
|
334
415
|
* @returns The download URL for the file
|
|
335
416
|
* @throws {Error} If the vault service returns an invalid response
|
|
336
417
|
* @throws {Error} If not file ID, name or content is set
|
|
337
418
|
* @throws {FetchError} If the download URL fetch fails
|
|
338
419
|
*/
|
|
339
|
-
async getDownloadUrl() {
|
|
420
|
+
async getDownloadUrl(options) {
|
|
340
421
|
if (this.lastDownloadUrl && this.lastDownloadUrl.expiresAt > /* @__PURE__ */ new Date()) {
|
|
341
422
|
return this.lastDownloadUrl.url;
|
|
342
423
|
}
|
|
@@ -346,7 +427,8 @@ class VaultFile {
|
|
|
346
427
|
const id = this.id ?? this.metadata?.id ?? (this.content ? await getFileHash(this.content) : this.name);
|
|
347
428
|
const response = await this._fetch({
|
|
348
429
|
method: "GET",
|
|
349
|
-
path: `/v2/files/${id}
|
|
430
|
+
path: `/v2/files/${id}`,
|
|
431
|
+
signal: options?.signal
|
|
350
432
|
});
|
|
351
433
|
this.lastDownloadUrl = { url: new URL(response.url), expiresAt: new Date(response.expiresAt) };
|
|
352
434
|
return this.lastDownloadUrl.url;
|
|
@@ -357,29 +439,48 @@ class VaultFile {
|
|
|
357
439
|
* @example
|
|
358
440
|
* ```ts
|
|
359
441
|
* const file = new File(['content'], 'document.txt')
|
|
360
|
-
* const vaultFile = await VaultFile.
|
|
442
|
+
* const vaultFile = await VaultFile.fromContent({
|
|
443
|
+
* name: 'document.txt',
|
|
444
|
+
* content: file,
|
|
445
|
+
* config: {
|
|
446
|
+
* vaultUrl,
|
|
447
|
+
* authStrategy,
|
|
448
|
+
* },
|
|
449
|
+
* })
|
|
361
450
|
* await vaultFile.upload(file)
|
|
362
451
|
* ```
|
|
363
452
|
*
|
|
364
453
|
* @param file - The file to upload to the vault. If not provided, the file content will be taken from the `content` property.
|
|
454
|
+
* @param url - The URL to upload the file to. If not provided, the upload URL will be fetched from the vault.
|
|
455
|
+
* @param options - The options for the request
|
|
456
|
+
* @param options.signal - The signal to abort the request
|
|
457
|
+
*
|
|
365
458
|
* @throws {FetchError} If the upload fails
|
|
366
459
|
* @throws {Error} If the file content is not set and no file is provided
|
|
367
460
|
* @returns Promise that resolves when upload is complete
|
|
368
461
|
*/
|
|
369
|
-
async upload(file, url) {
|
|
370
|
-
|
|
371
|
-
|
|
462
|
+
async upload(file, url, options) {
|
|
463
|
+
const content = file ?? this.content;
|
|
464
|
+
if (!content) {
|
|
465
|
+
throw new Error("Missing file content. Use fromContent() to create a file with content, or provide a file to upload.");
|
|
372
466
|
}
|
|
373
467
|
const uploadUrl = url ?? await this.getUploadUrl();
|
|
468
|
+
const mimeType = this.metadata?.mimeType ?? await detectFileMimeType(content);
|
|
469
|
+
const headers = new Headers();
|
|
470
|
+
if (mimeType)
|
|
471
|
+
headers.set("Content-Type", mimeType);
|
|
374
472
|
await wrappedFetch(uploadUrl, {
|
|
375
473
|
method: "PUT",
|
|
376
|
-
body:
|
|
474
|
+
body: content,
|
|
475
|
+
headers,
|
|
476
|
+
signal: options?.signal
|
|
377
477
|
});
|
|
378
478
|
}
|
|
379
|
-
async download(responseType = "blob") {
|
|
380
|
-
const downloadUrl = await this.getDownloadUrl();
|
|
479
|
+
async download(responseType = "blob", options) {
|
|
480
|
+
const downloadUrl = await this.getDownloadUrl({ signal: options?.signal });
|
|
381
481
|
const response = await wrappedFetch(downloadUrl, {
|
|
382
|
-
method: "GET"
|
|
482
|
+
method: "GET",
|
|
483
|
+
signal: options?.signal
|
|
383
484
|
});
|
|
384
485
|
const blob = await response.blob();
|
|
385
486
|
if (responseType === "blob")
|
|
@@ -388,48 +489,19 @@ class VaultFile {
|
|
|
388
489
|
}
|
|
389
490
|
}
|
|
390
491
|
|
|
391
|
-
var __defProp = Object.defineProperty;
|
|
392
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
393
|
-
var __publicField = (obj, key, value) => {
|
|
394
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
395
|
-
return value;
|
|
396
|
-
};
|
|
397
|
-
class DataTokenAuthStrategy {
|
|
398
|
-
constructor(dataToken) {
|
|
399
|
-
__publicField(this, "dataToken");
|
|
400
|
-
this.dataToken = dataToken;
|
|
401
|
-
}
|
|
402
|
-
getHeaders() {
|
|
403
|
-
return new Headers({
|
|
404
|
-
"x-data-token": this.dataToken
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
class APIKeyAuthStrategy {
|
|
409
|
-
constructor(apiKey) {
|
|
410
|
-
__publicField(this, "apiKey");
|
|
411
|
-
this.apiKey = apiKey;
|
|
412
|
-
}
|
|
413
|
-
getHeaders() {
|
|
414
|
-
return new Headers({
|
|
415
|
-
Authorization: this.apiKey
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
492
|
function vaultClient(config) {
|
|
421
|
-
function createFromContent(name, content) {
|
|
493
|
+
function createFromContent(name, content, options) {
|
|
422
494
|
return VaultFile.fromContent({
|
|
423
495
|
name,
|
|
424
496
|
content,
|
|
425
497
|
config
|
|
426
|
-
});
|
|
498
|
+
}, { signal: options?.signal });
|
|
427
499
|
}
|
|
428
|
-
function createFromReference(reference) {
|
|
500
|
+
function createFromReference(reference, options) {
|
|
429
501
|
return VaultFile.fromVaultReference({
|
|
430
502
|
reference,
|
|
431
503
|
config
|
|
432
|
-
});
|
|
504
|
+
}, { signal: options?.signal });
|
|
433
505
|
}
|
|
434
506
|
return { createFromContent, createFromReference };
|
|
435
507
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meistrari/vault-sdk",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -18,20 +18,16 @@
|
|
|
18
18
|
"files": [
|
|
19
19
|
"dist"
|
|
20
20
|
],
|
|
21
|
-
"scripts": {
|
|
22
|
-
"test": "vitest",
|
|
23
|
-
"build": "unbuild",
|
|
24
|
-
"lint": "eslint .",
|
|
25
|
-
"lint:fix": "eslint . --fix",
|
|
26
|
-
"check": "bun run lint && bun tsc --noEmit"
|
|
27
|
-
},
|
|
28
21
|
"dependencies": {
|
|
29
|
-
"
|
|
22
|
+
"file-type": "21.0.0",
|
|
23
|
+
"mime-types": "3.0.1",
|
|
30
24
|
"ofetch": "1.4.1",
|
|
31
|
-
"zod": "3.23.8"
|
|
25
|
+
"zod": "3.23.8",
|
|
26
|
+
"@meistrari/vault-shared": "0.0.3"
|
|
32
27
|
},
|
|
33
28
|
"devDependencies": {
|
|
34
29
|
"@types/bun": "latest",
|
|
30
|
+
"@types/mime-types": "3.0.1",
|
|
35
31
|
"msw": "2.6.8",
|
|
36
32
|
"unbuild": "2.0.0",
|
|
37
33
|
"vitest": "2.1.9"
|
|
@@ -41,5 +37,12 @@
|
|
|
41
37
|
},
|
|
42
38
|
"publishConfig": {
|
|
43
39
|
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"test": "vitest",
|
|
43
|
+
"build": "unbuild",
|
|
44
|
+
"lint": "eslint .",
|
|
45
|
+
"lint:fix": "eslint . --fix",
|
|
46
|
+
"check": "bun run lint && bun tsc --noEmit"
|
|
44
47
|
}
|
|
45
|
-
}
|
|
48
|
+
}
|