@leancodepl/login-manager 9.7.3 → 9.7.4
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/CHANGELOG.md +12 -0
- package/dist/index.js +42 -20
- package/dist/index.umd.cjs +1 -1
- package/dist/lib/baseLoginManager.d.ts +2 -0
- package/dist/lib/baseLoginManager.d.ts.map +1 -1
- package/package.json +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See
|
|
4
4
|
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [9.7.4](https://github.com/leancodepl/js_corelibrary/compare/v9.7.3...v9.7.4) (2026-02-10)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- prevent concurrent token refresh causing logout in multiple tabs
|
|
11
|
+
([e92e515](https://github.com/leancodepl/js_corelibrary/commit/e92e5156aacc7c68604780a09c0c0f2c35595de2))
|
|
12
|
+
|
|
13
|
+
# Change Log
|
|
14
|
+
|
|
15
|
+
All notable changes to this project will be documented in this file. See
|
|
16
|
+
[Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
17
|
+
|
|
6
18
|
## [9.7.3](https://github.com/leancodepl/js_corelibrary/compare/v9.7.2...v9.7.3) (2026-02-10)
|
|
7
19
|
|
|
8
20
|
### Bug Fixes
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
const a = "token_refresh_lock";
|
|
2
|
+
class h {
|
|
2
3
|
/* eslint-disable-next-line max-params */
|
|
3
|
-
constructor(e, t, s, n,
|
|
4
|
-
this.storage = e, this.endpoint = t, this.clientSecret = s, this.clientId = n, this.scopes =
|
|
4
|
+
constructor(e, t, s, n, u, o) {
|
|
5
|
+
this.storage = e, this.endpoint = t, this.clientSecret = s, this.clientId = n, this.scopes = u, this.additionalParams = o, s || (this.additionalParams = {
|
|
5
6
|
...o,
|
|
6
7
|
client_id: n
|
|
7
8
|
});
|
|
@@ -31,13 +32,34 @@ class a {
|
|
|
31
32
|
const e = await this.storage.getToken();
|
|
32
33
|
return e !== null ? await this.tryRefreshTokenInternal(e) : null;
|
|
33
34
|
}
|
|
34
|
-
tryRefreshTokenInternal(e) {
|
|
35
|
-
return this.isRefreshingToken || (this.isRefreshingToken = !0,
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
async tryRefreshTokenInternal(e) {
|
|
36
|
+
return typeof navigator < "u" && "locks" in navigator ? await this.tryRefreshWithLock(e) : (this.isRefreshingToken || (this.isRefreshingToken = !0, (async () => {
|
|
37
|
+
try {
|
|
38
|
+
const s = await this.acquireToken(this.buildRefreshRequest(e));
|
|
39
|
+
this.refreshTokenCallbacks.forEach((n) => n(s.type === "success"));
|
|
40
|
+
} catch {
|
|
41
|
+
this.refreshTokenCallbacks.forEach((s) => s(!1));
|
|
42
|
+
} finally {
|
|
43
|
+
this.isRefreshingToken = !1, this.refreshTokenCallbacks = [];
|
|
44
|
+
}
|
|
45
|
+
})()), new Promise((t) => {
|
|
38
46
|
this.refreshTokenCallbacks.push(t);
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
async tryRefreshWithLock(e) {
|
|
50
|
+
return await navigator.locks.request(a, { ifAvailable: !0 }, async (t) => {
|
|
51
|
+
if (!t)
|
|
52
|
+
return await this.waitForLockRelease();
|
|
53
|
+
try {
|
|
54
|
+
return (await this.acquireToken(this.buildRefreshRequest(e))).type === "success";
|
|
55
|
+
} catch {
|
|
56
|
+
return !1;
|
|
57
|
+
}
|
|
39
58
|
});
|
|
40
59
|
}
|
|
60
|
+
async waitForLockRelease() {
|
|
61
|
+
return await navigator.locks.request(a, async () => await this.storage.getToken() !== null);
|
|
62
|
+
}
|
|
41
63
|
onChange(e) {
|
|
42
64
|
this.callbacks.push(e);
|
|
43
65
|
}
|
|
@@ -143,7 +165,7 @@ class r extends Error {
|
|
|
143
165
|
super(e), this.name = "CannotRefreshTokenError", Object.setPrototypeOf(this, r.prototype);
|
|
144
166
|
}
|
|
145
167
|
}
|
|
146
|
-
class
|
|
168
|
+
class l extends h {
|
|
147
169
|
async signOut() {
|
|
148
170
|
await this.storage.resetToken(), this.notify(!1);
|
|
149
171
|
}
|
|
@@ -166,7 +188,7 @@ class u extends a {
|
|
|
166
188
|
this.notify(e);
|
|
167
189
|
}
|
|
168
190
|
}
|
|
169
|
-
class
|
|
191
|
+
class c {
|
|
170
192
|
constructor(e, t) {
|
|
171
193
|
this.facebookAppId = e, this.facebookPermissions = t, this.isSignedIn = void 0, this.token = "";
|
|
172
194
|
}
|
|
@@ -207,7 +229,7 @@ class l {
|
|
|
207
229
|
});
|
|
208
230
|
}
|
|
209
231
|
}
|
|
210
|
-
class
|
|
232
|
+
class k {
|
|
211
233
|
constructor(e = "token", t = "refresh_token", s = "expiration_date") {
|
|
212
234
|
this.tokenKey = e, this.refreshKey = t, this.expiryKey = s;
|
|
213
235
|
}
|
|
@@ -237,7 +259,7 @@ class c {
|
|
|
237
259
|
localStorage.removeItem(e);
|
|
238
260
|
}
|
|
239
261
|
}
|
|
240
|
-
class
|
|
262
|
+
class g {
|
|
241
263
|
token = null;
|
|
242
264
|
getToken() {
|
|
243
265
|
return this.token;
|
|
@@ -253,7 +275,7 @@ class k {
|
|
|
253
275
|
return this.token = null, Promise.resolve();
|
|
254
276
|
}
|
|
255
277
|
}
|
|
256
|
-
class
|
|
278
|
+
class d {
|
|
257
279
|
constructor(e = "token", t = "refresh_token", s = "expiration_date") {
|
|
258
280
|
this.tokenKey = e, this.refreshKey = t, this.expiryKey = s;
|
|
259
281
|
}
|
|
@@ -283,7 +305,7 @@ class g {
|
|
|
283
305
|
sessionStorage.removeItem(e);
|
|
284
306
|
}
|
|
285
307
|
}
|
|
286
|
-
class
|
|
308
|
+
class f extends h {
|
|
287
309
|
signOut() {
|
|
288
310
|
this.storage.resetToken(), this.notify(!1);
|
|
289
311
|
}
|
|
@@ -303,12 +325,12 @@ class d extends a {
|
|
|
303
325
|
}
|
|
304
326
|
}
|
|
305
327
|
export {
|
|
306
|
-
|
|
307
|
-
|
|
328
|
+
l as AsyncLoginManager,
|
|
329
|
+
h as BaseLoginManager,
|
|
308
330
|
r as CannotRefreshTokenError,
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
331
|
+
c as FacebookClient,
|
|
332
|
+
k as LocalTokenStorage,
|
|
333
|
+
g as MemoryTokenStorage,
|
|
334
|
+
d as SessionTokenStorage,
|
|
335
|
+
f as SyncLoginManager
|
|
314
336
|
};
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(n,r){typeof exports=="object"&&typeof module<"u"?r(exports):typeof define=="function"&&define.amd?define(["exports"],r):(n=typeof globalThis<"u"?globalThis:n||self,r(n["@leancodepl/login-manager"]={}))})(this,(function(n){"use strict";class
|
|
1
|
+
(function(n,r){typeof exports=="object"&&typeof module<"u"?r(exports):typeof define=="function"&&define.amd?define(["exports"],r):(n=typeof globalThis<"u"?globalThis:n||self,r(n["@leancodepl/login-manager"]={}))})(this,(function(n){"use strict";const r="token_refresh_lock";class h{constructor(e,t,s,i,y,u){this.storage=e,this.endpoint=t,this.clientSecret=s,this.clientId=i,this.scopes=y,this.additionalParams=u,s||(this.additionalParams={...u,client_id:i})}callbacks=[];refreshTokenCallbacks=[];isRefreshingToken=!1;trySignIn(e,t){return this.acquireToken(this.buildSignInRequest(e,t))}trySignInWithFacebook(e){return this.acquireToken(this.buildSignInWithFacebookRequest(e))}trySignInWithOneTimeToken(e){return this.acquireToken(this.buildSignInWithOneTimeTokenRequest(e))}trySignInWithGoogle(e){return this.acquireToken(this.buildSignInWithGoogleRequest(e))}trySignInWithLinkedIn(e){return this.acquireToken(this.buildSignInWithLinkedInRequest(e))}trySignInWithApple(e){return this.acquireToken(this.buildSignInWithAppleRequest(e))}async tryRefreshToken(){const e=await this.storage.getToken();return e!==null?await this.tryRefreshTokenInternal(e):null}async tryRefreshTokenInternal(e){return typeof navigator<"u"&&"locks"in navigator?await this.tryRefreshWithLock(e):(this.isRefreshingToken||(this.isRefreshingToken=!0,(async()=>{try{const s=await this.acquireToken(this.buildRefreshRequest(e));this.refreshTokenCallbacks.forEach(i=>i(s.type==="success"))}catch{this.refreshTokenCallbacks.forEach(s=>s(!1))}finally{this.isRefreshingToken=!1,this.refreshTokenCallbacks=[]}})()),new Promise(t=>{this.refreshTokenCallbacks.push(t)}))}async tryRefreshWithLock(e){return await navigator.locks.request(r,{ifAvailable:!0},async t=>{if(!t)return await this.waitForLockRelease();try{return(await this.acquireToken(this.buildRefreshRequest(e))).type==="success"}catch{return!1}})}async waitForLockRelease(){return await navigator.locks.request(r,async()=>await this.storage.getToken()!==null)}onChange(e){this.callbacks.push(e)}removeOnChange(e){const t=this.callbacks.indexOf(e);t!==-1&&this.callbacks.splice(t,1)}async acquireToken(e){try{const t=await fetch(this.endpoint+"/connect/token",e);if(!t.ok)return t.status===400&&await this.signOut(),{type:"failure"};const s=await t.json(),i=new Date;return i.setSeconds(new Date().getSeconds()+s.expires_in),await this.storage.storeToken({token:s.access_token,refreshToken:s.refresh_token,expirationDate:i}),this.notify(!0),{type:"success"}}catch(t){return console.warn("Cannot call Auth server, error: ",t),{type:"networkError"}}}buildSignInRequest(e,t){const s={grant_type:"password",scope:this.scopes,username:e,password:t,...this.additionalParams};return{method:"POST",headers:this.prepareHeaders(),body:new URLSearchParams(s)}}buildSignInWithOneTimeTokenRequest(e){const t={grant_type:"onetime",scope:this.scopes,token:e,...this.additionalParams};return{method:"POST",headers:this.prepareHeaders(),body:new URLSearchParams(t)}}buildAssertionSignInRequest(e,t){const s={grant_type:t,scope:this.scopes,assertion:e,...this.additionalParams};return{method:"POST",headers:this.prepareHeaders(),body:new URLSearchParams(s)}}buildSignInWithFacebookRequest(e){return this.buildAssertionSignInRequest(e,"facebook")}buildSignInWithGoogleRequest(e){return this.buildAssertionSignInRequest(e,"google")}buildSignInWithLinkedInRequest(e){return this.buildAssertionSignInRequest(e,"linkedin")}buildSignInWithAppleRequest(e){return this.buildAssertionSignInRequest(e,"apple")}buildRefreshRequest(e){const t={grant_type:"refresh_token",scope:this.scopes,refresh_token:e.refreshToken||"",...this.additionalParams};return{method:"POST",headers:this.prepareHeaders(),body:new URLSearchParams(t)}}prepareHeaders(){const e=new Headers;if(this.clientSecret){const t=btoa(`${this.clientId}:${this.clientSecret}`);e.append("Authorization","Basic "+t)}return e.append("Content-Type","application/x-www-form-urlencoded"),e}notify(e){for(const t of this.callbacks)t(e)}}class a extends Error{constructor(e){super(e),this.name="CannotRefreshTokenError",Object.setPrototypeOf(this,a.prototype)}}class l extends h{async signOut(){await this.storage.resetToken(),this.notify(!1)}async isSigned(){return await this.storage.getToken()!==null}async getToken(){const e=await this.storage.getToken();if(e===null)return null;if(e.expirationDate<new Date){if(await this.tryRefreshTokenInternal(e))return(await this.storage.getToken())?.token??null;throw new a("Cannot refresh access token after it has expired")}else return e.token}async load(){const e=await this.isSigned();this.notify(e)}}class c{constructor(e,t){this.facebookAppId=e,this.facebookPermissions=t,this.isSignedIn=void 0,this.token=""}isSignedIn;token;get accessToken(){return this.token}setup(e){const t=document.getElementsByTagName("script")[0],s="facebook-jssdk";if(document.getElementById(s)){this.initializeSDK(),this.getLoginStatus(e);return}const i=document.createElement("script");i.id=s,i.async=!0,i.src="//connect.facebook.net/pl_PL/sdk.js",t.parentNode!=null&&t.parentNode.insertBefore(i,t),i.onload=()=>{this.initializeSDK(),this.getLoginStatus(e)}}login(e){FB.login(t=>{t.status==="connected"?(this.isSignedIn=!0,this.token=t.authResponse.accessToken,e&&e(t.authResponse.accessToken)):this.isSignedIn=!1},{scope:this.facebookPermissions})}getLoginStatus(e){FB.getLoginStatus(t=>{t.status==="connected"?(this.isSignedIn=!0,this.token=t.authResponse.accessToken,e&&e(t.authResponse.accessToken)):this.isSignedIn=!1})}initializeSDK(){FB.init({appId:this.facebookAppId,xfbml:!0,version:"v2.9"})}}class k{constructor(e="token",t="refresh_token",s="expiration_date"){this.tokenKey=e,this.refreshKey=t,this.expiryKey=s}getToken(){return this.hasValue(this.tokenKey)?{token:this.getValue(this.tokenKey),refreshToken:this.getValue(this.refreshKey),expirationDate:new Date(Number(this.getValue(this.expiryKey)))}:null}storeToken(e){this.setValue(this.tokenKey,e.token),this.setValue(this.refreshKey,e.refreshToken),this.setValue(this.expiryKey,e.expirationDate.getTime().toString())}resetToken(){this.remove(this.tokenKey),this.remove(this.refreshKey),this.remove(this.expiryKey)}hasValue(e){return localStorage.getItem(e)!==null}getValue(e){return localStorage.getItem(e)}setValue(e,t){localStorage.setItem(e,t)}remove(e){localStorage.removeItem(e)}}class g{token=null;getToken(){return this.token}storeToken(e){return this.token={token:e.token,refreshToken:e.refreshToken,expirationDate:e.expirationDate},Promise.resolve()}resetToken(){return this.token=null,Promise.resolve()}}class d{constructor(e="token",t="refresh_token",s="expiration_date"){this.tokenKey=e,this.refreshKey=t,this.expiryKey=s}getToken(){return this.hasValue(this.tokenKey)?{token:this.getValue(this.tokenKey),refreshToken:this.getValue(this.refreshKey),expirationDate:new Date(Number(this.getValue(this.expiryKey)))}:null}storeToken(e){this.setValue(this.tokenKey,e.token),this.setValue(this.refreshKey,e.refreshToken),this.setValue(this.expiryKey,e.expirationDate.getTime().toString())}resetToken(){this.remove(this.tokenKey),this.remove(this.refreshKey),this.remove(this.expiryKey)}hasValue(e){return sessionStorage.getItem(e)!==null}getValue(e){return sessionStorage.getItem(e)}setValue(e,t){sessionStorage.setItem(e,t)}remove(e){sessionStorage.removeItem(e)}}class f extends h{signOut(){this.storage.resetToken(),this.notify(!1)}isSigned(){return this.storage.getToken()!==null}async getToken(){const e=this.storage.getToken();if(e===null)return null;if(e.expirationDate<new Date){if(await this.tryRefreshTokenInternal(e))return this.storage.getToken()?.token??null;throw new a("Cannot refresh access token after it has expired")}else return e.token}}n.AsyncLoginManager=l,n.BaseLoginManager=h,n.CannotRefreshTokenError=a,n.FacebookClient=c,n.LocalTokenStorage=k,n.MemoryTokenStorage=g,n.SessionTokenStorage=d,n.SyncLoginManager=f,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})}));
|
|
@@ -33,6 +33,8 @@ export declare abstract class BaseLoginManager<TStorage extends TokenStorage> {
|
|
|
33
33
|
trySignInWithApple(accessToken: string): Promise<LoginResult>;
|
|
34
34
|
tryRefreshToken(): Promise<boolean | null>;
|
|
35
35
|
protected tryRefreshTokenInternal(token: Token): Promise<boolean>;
|
|
36
|
+
private tryRefreshWithLock;
|
|
37
|
+
private waitForLockRelease;
|
|
36
38
|
onChange(callback: (isSignedIn: boolean) => void): void;
|
|
37
39
|
removeOnChange(callback: (isSignedIn: boolean) => void): void;
|
|
38
40
|
acquireToken(init: RequestInit): Promise<LoginResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baseLoginManager.d.ts","sourceRoot":"","sources":["../../src/lib/baseLoginManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAEvE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAC9B;AAED,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,iBAAiB,GAAG,YAAY,CAAA;AAGzE,MAAM,WAAW,YAAa,SAAQ,gBAAgB,CAAC,YAAY,CAAC;CAAG;
|
|
1
|
+
{"version":3,"file":"baseLoginManager.d.ts","sourceRoot":"","sources":["../../src/lib/baseLoginManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAEvE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAC9B;AAED,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,iBAAiB,GAAG,YAAY,CAAA;AAGzE,MAAM,WAAW,YAAa,SAAQ,gBAAgB,CAAC,YAAY,CAAC;CAAG;AAIvE,8BAAsB,gBAAgB,CAAC,QAAQ,SAAS,YAAY;IAOhE,SAAS,CAAC,OAAO,EAAE,QAAQ;IAC3B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,QAAQ;IAChB,SAAS,CAAC,MAAM,EAAE,MAAM;IACxB,SAAS,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAXrD,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,qBAAqB,CAAqC;IAClE,OAAO,CAAC,iBAAiB,CAAQ;gBAIrB,OAAO,EAAE,QAAQ,EACnB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,QAAQ,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAA;aAUrC,OAAO,IAAI,QAAQ,SAAS,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;aAEpE,QAAQ,IAAI,QAAQ,SAAS,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO;aAE3E,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAE3C,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAInE,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAIhE,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAI9D,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAI9D,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAIhE,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAIvD,eAAe;cASZ,uBAAuB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;YA4BzD,kBAAkB;YAelB,kBAAkB;IAOzB,QAAQ,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI;IAIhD,cAAc,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI;IAOhD,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IA6B3D,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW;IAgB1E,OAAO,CAAC,kCAAkC;IAenC,2BAA2B,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,WAAW;IAevF,OAAO,CAAC,8BAA8B;IAItC,OAAO,CAAC,4BAA4B;IAIpC,OAAO,CAAC,8BAA8B;IAItC,OAAO,CAAC,2BAA2B;IAInC,OAAO,CAAC,mBAAmB;IAe3B,SAAS,CAAC,cAAc;IAWxB,SAAS,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO;CAKrC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leancodepl/login-manager",
|
|
3
|
-
"version": "9.7.
|
|
3
|
+
"version": "9.7.4",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -53,5 +53,8 @@
|
|
|
53
53
|
"dist",
|
|
54
54
|
"CHANGELOG.md",
|
|
55
55
|
"!**/*.tsbuildinfo"
|
|
56
|
-
]
|
|
56
|
+
],
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"vitest": "*"
|
|
59
|
+
}
|
|
57
60
|
}
|