@gw2me/client 0.8.2 → 0.9.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 +202 -7
- package/dist/chunk-EXOYQILJ.js +1 -0
- package/dist/chunk-OSZ7DOEH.js +1 -0
- package/dist/dpop.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/pkce.js +1 -1
- package/package.json +15 -12
package/README.md
CHANGED
|
@@ -2,21 +2,216 @@
|
|
|
2
2
|
|
|
3
3
|
This is a client library to interact with the gw2.me API.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm i @gw2me/client
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## API
|
|
12
|
+
|
|
13
|
+
This section shows basic examples and concepts on how to use the different functions provided by this library. For all parameters, please check the typescript types.
|
|
14
|
+
|
|
15
|
+
### `Gw2MeClient`
|
|
16
|
+
|
|
17
|
+
The `Gw2MeClient` class is the main entry point into using this library. You can pass your client id and, for confidential clients, the optional client secret. The second optional parameter takes an options object, which currently can be used to override the `url` of gw2.me, for example when developing against a local instance.
|
|
18
|
+
|
|
19
|
+
All these functions are usually also provided by default OAuth2 libraries. If you just care about accessing the gw2.me specific APIs, you can skip this section and continue to [`Gw2MeApi`](#gw2meapi).
|
|
20
|
+
|
|
6
21
|
|
|
7
22
|
```ts
|
|
8
|
-
|
|
23
|
+
const client = new Gw2MeClient(client: { clientId: string, clientSecret?: string }, options?: Partial<{ url: string }>)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
#### `getAuthorizationUrl`
|
|
9
27
|
|
|
10
|
-
|
|
11
|
-
const url = client.getAuthorizationUrl({ /* ... */ });
|
|
28
|
+
`client.getAuthorizationUrl` can be used to create a authorization url. You can read more about the available parameters on https://gw2.me/dev/docs/access-tokens.
|
|
12
29
|
|
|
13
|
-
|
|
30
|
+
```ts
|
|
31
|
+
// create auth url
|
|
32
|
+
const authUrl = client.getAuthorizationUrl({
|
|
33
|
+
redirect_uri: 'https://example.com/auth/callback',
|
|
34
|
+
scopes: [Scope.Identify],
|
|
35
|
+
// ...additional properties here
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// redirect the user to the auth url
|
|
39
|
+
location.href = authUrl;
|
|
14
40
|
```
|
|
15
41
|
|
|
16
|
-
|
|
42
|
+
#### `pushAuthorizationRequest`
|
|
43
|
+
|
|
44
|
+
`client.pushAuthorizationRequest` can be used for Pushed Authorization Requests (PAR). Read more about PAR on https://gw2.me/dev/docs/access-tokens#par.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
// create pushed authorization request
|
|
48
|
+
const pushedRequest = await client.pushAuthorizationRequest({
|
|
49
|
+
redirect_uri: 'https://example.com/auth/callback',
|
|
50
|
+
scopes: [Scope.Identify],
|
|
51
|
+
// ...additional properties here
|
|
52
|
+
});
|
|
17
53
|
|
|
54
|
+
// get url for the pushed authorization request
|
|
55
|
+
const authUrl = client.getAuthorizationUrl(pushedRequest);
|
|
56
|
+
|
|
57
|
+
// redirect the user to the auth url
|
|
58
|
+
location.href = authUrl;
|
|
18
59
|
```
|
|
19
|
-
|
|
60
|
+
|
|
61
|
+
#### `parseAuthorizationResponseSearchParams`
|
|
62
|
+
|
|
63
|
+
`client.parseAuthorizationResponseSearchParams` parses search url parameters to extract the code or error.
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
const searchParams = new URLSearchParams(location.search);
|
|
67
|
+
const { code } = client.parseAuthorizationResponseSearchParams(searchParams);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
#### `getAccessToken`
|
|
72
|
+
|
|
73
|
+
`client.getAccessToken` exchanges an authorization token for an access token, which can be used to call the gw2.me API.
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
const accessToken = await client.getAccessToken({ code });
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
#### `refreshToken`
|
|
80
|
+
|
|
81
|
+
`client.refreshToken` uses a refresh token to receive a new access token. See https://gw2.me/dev/docs/refresh-tokens for more information on refreshing tokens.
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
const accessToken = await client.refreshToken({ refresh_token });
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### `revokeToken`
|
|
88
|
+
|
|
89
|
+
`client.revokeToken` can be used to revoke a (access or refresh) token that is no longer needed.
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
await client.revokeToken({ token });
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### `introspectToken`
|
|
96
|
+
|
|
97
|
+
`client.introspectToken` returns information about an access or refresh token.
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
const info = await client.introspectToken({ token });
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### `Gw2MeApi`
|
|
104
|
+
|
|
105
|
+
The `Gw2MeApi` class provides access to the gw2.me API. This can be useful even if using a standard OAuth2 library for the initial OAuth2 flow instead of the functions described above.
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
const api = client.api(accessToken);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### `user`
|
|
112
|
+
|
|
113
|
+
`api.user` returns the current user. See https://gw2.me/dev/docs/users for more information.
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
const user = await api.user();
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### `saveSettings`
|
|
120
|
+
|
|
121
|
+
`api.saveSettings` stores settings for the current user. See https://gw2.me/dev/docs/users for more information.
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
await api.saveSettings({ foo: 'bar' });
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### `accounts`
|
|
128
|
+
|
|
129
|
+
`api.accounts` gets all the authorized Guild Wars 2 accounts for the current user. See https://gw2.me/dev/docs/gw2-api#accounts for more information.
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
const accounts = await api.accounts();
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### `subtoken`
|
|
136
|
+
|
|
137
|
+
`api.subtoken` requests a subtoken for the given account of the user. The subtoken can be used to make authenticated requests against the official Guild Wars 2 API. See https://gw2.me/dev/docs/gw2-api#subtoken for more information.
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
const subtoken = await api.subtoken(accountId);
|
|
141
|
+
|
|
142
|
+
// you can also request a limited set of permissions
|
|
143
|
+
const subtoken = await api.subtoken(accountId, { permissions: ['account'] });
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### FedCM
|
|
147
|
+
|
|
148
|
+
FedCM is a browser API for privacy-preserving federated authentication without the need for third-party cookies and redirects. It is described in more detail on https://gw2.me/dev/docs/fed-cm.
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
// check if FedCM is supported in the current browser
|
|
152
|
+
const isSupported = client.fedCM.isSupported();
|
|
153
|
+
|
|
154
|
+
// initiate a FedCM request
|
|
155
|
+
const { token: code } = await client.fedCM.request({
|
|
156
|
+
scopes: [Scope.Identify],
|
|
157
|
+
// ...additional properties here
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// The received code can now be exchanged for an access token using the regular client functions
|
|
161
|
+
const accessToken = await client.getAccessToken({ code });
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### PCKE
|
|
165
|
+
|
|
166
|
+
Proof Key for Code Exchange (PKCE) is a method to prevent code interception attacks. You can read more about it on https://gw2.me/dev/docs/access-tokens#pkce. It is highly recommended you use PKCE.
|
|
167
|
+
|
|
168
|
+
This library provides a helper functions to generate code challenges.
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
import { generatePKCEPair } from '@gw2me/client/pkce';
|
|
172
|
+
|
|
173
|
+
const { code_verifier, challenge } = await generatePKCEPair();
|
|
174
|
+
|
|
175
|
+
// pass the generated challenge when creating the authorization url
|
|
176
|
+
const authUrl = client.getAuthorizationUrl({
|
|
177
|
+
redirect_uri: 'https://example.com/auth/callback',
|
|
178
|
+
scopes: [Scope.Identify],
|
|
179
|
+
...challenge,
|
|
180
|
+
// ...additional properties here
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// ...
|
|
184
|
+
|
|
185
|
+
// later use the verifier when exchanging the code for the access token
|
|
186
|
+
const accessToken = await client.getAccessToken({ code, code_verifier });
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### DPoP
|
|
190
|
+
|
|
191
|
+
DPoP is a method to prevent replay attacks by binding the access token to the client. You can read more about DPoP on https://gw2.me/dev/docs/access-tokens#dpop.
|
|
192
|
+
|
|
193
|
+
All client functions that can use DPoP take a `dpop` callback as parameter, which should return the DPoP proof. This library exports some basic functions to get you started with using DPoP.
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
import { generateDPoPKeyPair, createDPoPJwt, jwkThumbprint } from '@gw2me/client/dpop';
|
|
197
|
+
|
|
198
|
+
// create a DPoP key pair
|
|
199
|
+
const dpop = await generateDPoPKeyPair();
|
|
200
|
+
// TODO: store the dpop keys securely, as dpop bound tokens can only be used in combination with these keys
|
|
201
|
+
|
|
202
|
+
// create a DPoP bound authorization url by passing the thumbprint of the public key
|
|
203
|
+
const authUrl = client.getAuthorizationUrl({
|
|
204
|
+
// ...
|
|
205
|
+
dpop_jkt: await jwkThumbprint(dpop.publicKey)
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// ...
|
|
209
|
+
|
|
210
|
+
// later exchange code for access token
|
|
211
|
+
const accessToken = await client.getAccessToken({
|
|
212
|
+
code,
|
|
213
|
+
dpop: (params) => createDPoPJwt(params, dpop),
|
|
214
|
+
});
|
|
20
215
|
```
|
|
21
216
|
|
|
22
217
|
## License
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function a(r){let e=r instanceof ArrayBuffer?new Uint8Array(r):r;return btoa(String.fromCharCode(...e)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}export{a};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var f=a=>{throw TypeError(a)};var d=(a,b,c)=>b.has(a)||f("Cannot "+c);var g=(a,b,c)=>(d(a,b,"read from private field"),c?c.call(a):b.get(a)),h=(a,b,c)=>b.has(a)?f("Cannot add the same private member more than once"):b instanceof WeakSet?b.add(a):b.set(a,c),i=(a,b,c,e)=>(d(a,b,"write to private field"),e?e.call(a,c):b.set(a,c),c),j=(a,b,c)=>(d(a,b,"access private method"),c);export{g as a,h as b,i as c,j as d};
|
package/dist/dpop.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{a as e}from"./chunk-EXOYQILJ.js";import"./chunk-OSZ7DOEH.js";function d(){return crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!1,["sign"])}async function m({htm:t,htu:n,nonce:r,accessToken:a},s){let c=JSON.stringify({alg:"ES256",typ:"dpop+jwt",jwk:await u(s.publicKey)}),y=JSON.stringify({iat:Math.floor(Date.now()/1e3),jti:e(crypto.getRandomValues(new Uint8Array(32))),htm:t,htu:n,nonce:r,ath:a?e(await crypto.subtle.digest("SHA-256",o(a))):void 0}),i=`${e(o(c))}.${e(o(y))}`,p={name:"ECDSA",hash:"SHA-256"},g=e(await crypto.subtle.sign(p,s.privateKey,o(i)));return`${i}.${g}`}var w=new TextEncoder;function o(t){return w.encode(t)}async function u(t){let{kty:n,e:r,k:a,n:s,x:c,y,crv:i}=await crypto.subtle.exportKey("jwk",t);return{e:r,k:a,crv:i,kty:n,n:s,x:c,y}}async function P(t){let n=JSON.stringify(await u(t)),r=await crypto.subtle.digest("SHA-256",o(n));return e(r)}export{m as createDPoPJwt,d as generateDPoPKeyPair,P as jwkThumbprint};
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{a as s,b as m,c as _,d as o}from"./chunk-OSZ7DOEH.js";var z=(p=>(p.Identify="identify",p.Email="email",p.Accounts="accounts",p.Accounts_Verified="accounts.verified",p.Accounts_DisplayName="accounts.displayName",p.GW2_Account="gw2:account",p.GW2_Inventories="gw2:inventories",p.GW2_Characters="gw2:characters",p.GW2_Tradingpost="gw2:tradingpost",p.GW2_Wallet="gw2:wallet",p.GW2_Unlocks="gw2:unlocks",p.GW2_Pvp="gw2:pvp",p.GW2_Wvw="gw2:wvw",p.GW2_Builds="gw2:builds",p.GW2_Progression="gw2:progression",p.GW2_Guilds="gw2:guilds",p))(z||{});var h=class extends Error{},v=class extends h{constructor(t,n,r){super(`Received ${t}`+(n?`: ${n}`:"")+(r?` (${r})`:""));this.error=t;this.error_description=n;this.error_uri=r}};async function l(u){if(await C(u),!(u.headers.get("Content-Type")==="application/json"))throw new h("gw2.me did not return a valid JSON response");return u.json()}async function C(u){if(!u.ok){let e;throw u.headers.get("Content-Type")==="application/json"&&(e=(await u.json()).error_description),new h(`gw2.me returned an error: ${e??"Unknown error"}`)}}var f,U,x,b=class{constructor(e,t){this.access_token=e;this.options=t;m(this,f)}user(){return o(this,f,x).call(this,"api/user").then(e=>fetch(e)).then(l)}saveSettings(e){return o(this,f,x).call(this,"api/user/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}).then(t=>fetch(t)).then(C)}accounts(){return o(this,f,x).call(this,"api/accounts").then(e=>fetch(e)).then(l)}subtoken(e,t){let n=o(this,f,U).call(this,`api/accounts/${e}/subtoken`);return t?.permissions&&n.searchParams.set("permissions",t.permissions.join(",")),o(this,f,x).call(this,n).then(r=>fetch(r)).then(l)}};f=new WeakSet,U=function(e){return new URL(e,this.options?.url||"https://gw2.me/")},x=async function(e,t){let n=e instanceof URL?e:o(this,f,U).call(this,e),r=this.options?.dpop,i=new Headers(t?.headers);return i.set("Authorization",`${r?"DPoP":"Bearer"} ${this.access_token}`),r&&i.set("DPoP",await r({htm:t?.method??"GET",htu:n.toString(),accessToken:this.access_token})),new Request(n,{cache:"no-cache",...t,headers:i})};var R,T,O=class{constructor(e,t){m(this,R);m(this,T);_(this,R,e),_(this,T,t)}isSupported(){return typeof window<"u"&&"IdentityCredential"in window}request({scopes:e,mediation:t,signal:n,mode:r,code_challenge:i,code_challenge_method:d}){if(!this.isSupported())throw new h("FedCM is not supported");return navigator.credentials.get({mediation:t,signal:n,identity:{providers:[{configURL:s(this,R),clientId:s(this,T),fields:[e.includes("identify")&&"name",e.includes("email")&&"email"].filter(Boolean),nonce:`${d}:${i}`,params:{scope:e.join(" "),code_challenge:i,code_challenge_method:d}}],mode:r}})}};R=new WeakMap,T=new WeakMap;var a,A,c,P,y,S=class{constructor(e,t){this.options=t;m(this,c);m(this,a);m(this,A);_(this,a,e),_(this,A,new O(o(this,c,P).call(this,"/fed-cm/config.json"),e.client_id))}getAuthorizationUrl(e){let t="request_uri"in e?new URLSearchParams({client_id:s(this,a).client_id,response_type:"code",request_uri:e.request_uri}):q(s(this,a).client_id,e);return o(this,c,P).call(this,`/oauth2/authorize?${t.toString()}`).toString()}async pushAuthorizationRequest(e){let t=o(this,c,P).call(this,"/oauth2/par"),n={"Content-Type":"application/x-www-form-urlencoded"};e.dpop&&(n.DPoP=await e.dpop({htm:"POST",htu:t.toString()}));let r=q(s(this,a).client_id,e);return s(this,a).client_secret&&(n.Authorization=o(this,c,y).call(this)),await fetch(t,{method:"POST",headers:n,body:r,cache:"no-store"}).then(l)}async getAccessToken({code:e,token_type:t,redirect_uri:n,code_verifier:r,dpop:i}){let d=new URLSearchParams({grant_type:"authorization_code",code:e,client_id:s(this,a).client_id,redirect_uri:n}),g={"Content-Type":"application/x-www-form-urlencoded"};s(this,a).client_secret&&(g.Authorization=o(this,c,y).call(this)),r&&d.set("code_verifier",r);let w=o(this,c,P).call(this,"/api/token");return i&&(g.DPoP=await i({htm:"POST",htu:w.toString(),accessToken:t==="DPoP"?e:void 0})),await fetch(w,{method:"POST",headers:g,body:d,cache:"no-store"}).then(l)}async refreshToken({refresh_token:e,refresh_token_type:t,dpop:n}){let r=new URLSearchParams({grant_type:"refresh_token",refresh_token:e,client_id:s(this,a).client_id}),i={"Content-Type":"application/x-www-form-urlencoded"};s(this,a).client_secret&&(i.Authorization=o(this,c,y).call(this));let d=o(this,c,P).call(this,"/api/token");return n&&(i.DPoP=await n({htm:"POST",htu:d.toString(),accessToken:t==="DPoP"?e:void 0})),await fetch(d,{method:"POST",headers:i,body:r,cache:"no-store"}).then(l)}async revokeToken({token:e}){let t=new URLSearchParams({token:e}),n={"Content-Type":"application/x-www-form-urlencoded"};s(this,a).client_secret&&(n.Authorization=o(this,c,y).call(this)),await fetch(o(this,c,P).call(this,"/api/token/revoke"),{method:"POST",cache:"no-store",headers:n,body:t}).then(l)}async introspectToken({token:e}){let t=new URLSearchParams({token:e}),n={"Content-Type":"application/x-www-form-urlencoded"};return s(this,a).client_secret&&(n.Authorization=o(this,c,y).call(this)),await fetch(o(this,c,P).call(this,"/api/token/introspect"),{method:"POST",cache:"no-store",headers:n,body:t}).then(l)}parseAuthorizationResponseSearchParams(e){let t=o(this,c,P).call(this,"/").origin,n=e.get("iss");if(!n)throw new h("Issuer Identifier verification failed: parameter `iss` is missing");if(n!==t)throw new h(`Issuer Identifier verification failed: expected "${t}", got "${n}"`);let r=e.get("error");if(r){let g=e.get("error_description")??void 0,w=e.get("error_uri")??void 0;throw new v(r,g,w)}let i=e.get("code");if(!i)throw new h("Parameter `code` is missing");let d=e.get("state")||void 0;return{code:i,state:d}}api(e,t){return new b(e,{...this.options,...t})}get fedCM(){return s(this,A)}};a=new WeakMap,A=new WeakMap,c=new WeakSet,P=function(e){return new URL(e,this.options?.url||"https://gw2.me/")},y=function(){if(!s(this,a).client_secret)throw new h("client_secret is required");return`Basic ${btoa(`${s(this,a).client_id}:${s(this,a).client_secret}`)}`};function q(u,{redirect_uri:e,scopes:t,state:n,code_challenge:r,code_challenge_method:i,dpop_jkt:d,prompt:g,include_granted_scopes:w,verified_accounts_only:I}){let k=new URLSearchParams({client_id:u,response_type:"code",redirect_uri:e,scope:t.join(" ")});return n&&k.append("state",n),r&&i&&(k.append("code_challenge",r),k.append("code_challenge_method",i)),d&&k.append("dpop_jkt",d),g&&k.append("prompt",g),w&&k.append("include_granted_scopes","true"),I&&k.append("verified_accounts_only","true"),k}export{b as Gw2MeApi,S as Gw2MeClient,h as Gw2MeError,v as Gw2MeOAuthError,z as Scope};
|
package/dist/pkce.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{a as e}from"./chunk-EXOYQILJ.js";import"./chunk-OSZ7DOEH.js";async function a(){let n=new Uint8Array(32);crypto.getRandomValues(n);let r=e(n),c=new TextEncoder,o=await crypto.subtle.digest("SHA-256",c.encode(r));return{code_verifier:r,challenge:{code_challenge_method:"S256",code_challenge:e(new Uint8Array(o))}}}export{a as generatePKCEPair};
|
package/package.json
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gw2me/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "gw2.me client library",
|
|
5
|
-
"
|
|
6
|
-
"types": "./dist/index.d.ts",
|
|
5
|
+
"type": "module",
|
|
7
6
|
"exports": {
|
|
8
7
|
"./package.json": "./package.json",
|
|
9
8
|
".": {
|
|
@@ -40,21 +39,25 @@
|
|
|
40
39
|
},
|
|
41
40
|
"homepage": "https://github.com/gw2treasures/gw2.me#readme",
|
|
42
41
|
"devDependencies": {
|
|
43
|
-
"@gw2treasures/eslint-config": "0.
|
|
42
|
+
"@gw2treasures/eslint-config": "0.2.0",
|
|
44
43
|
"@gw2treasures/publish-package": "0.1.0-rc.0",
|
|
45
44
|
"@gw2treasures/tsconfig": "0.0.1",
|
|
46
|
-
"eslint": "9.
|
|
47
|
-
"tsup": "8.
|
|
48
|
-
"typescript": "5.
|
|
49
|
-
"typescript-eslint": "8.
|
|
50
|
-
"undici-types": "7.
|
|
45
|
+
"eslint": "9.39.1",
|
|
46
|
+
"tsup": "8.5.1",
|
|
47
|
+
"typescript": "5.9.3",
|
|
48
|
+
"typescript-eslint": "8.47.0",
|
|
49
|
+
"undici-types": "7.16.0"
|
|
50
|
+
},
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"access": "public",
|
|
53
|
+
"provenance": true
|
|
51
54
|
},
|
|
52
55
|
"scripts": {
|
|
53
56
|
"build": "pnpm run clean && if test $CI; then pnpm run build:ci; else pnpm run build:local; fi",
|
|
54
|
-
"build:local": "tsup src/index.ts src/dpop.ts src/pkce.ts && tsc --emitDeclarationOnly --declaration --declarationMap",
|
|
55
|
-
"build:ci": "tsup src/index.ts src/dpop.ts src/pkce.ts --minify --dts",
|
|
57
|
+
"build:local": "tsup src/index.ts src/dpop.ts src/pkce.ts --format esm && tsc --emitDeclarationOnly --declaration --declarationMap",
|
|
58
|
+
"build:ci": "tsup src/index.ts src/dpop.ts src/pkce.ts --format esm --minify --dts",
|
|
56
59
|
"clean": "rm -rf dist/",
|
|
57
|
-
"lint": "eslint
|
|
60
|
+
"lint": "eslint .",
|
|
58
61
|
"publish-package": "gw2treasures-publish-package"
|
|
59
62
|
}
|
|
60
63
|
}
|