@akira-io/billing-js 0.1.8 → 0.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/{client-types-B3lf4xBs.d.cts → client-types-CtRkHWna.d.cts} +21 -1
- package/dist/{client-types-B3lf4xBs.d.ts → client-types-CtRkHWna.d.ts} +21 -1
- package/dist/client.cjs +6 -0
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +3 -1
- package/dist/client.d.ts +3 -1
- package/dist/client.js +6 -0
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +239 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +82 -2
- package/dist/index.d.ts +82 -2
- package/dist/index.js +233 -1
- package/dist/index.js.map +1 -1
- package/dist/license.d.cts +1 -1
- package/dist/license.d.ts +1 -1
- package/dist/oauth.d.cts +1 -1
- package/dist/oauth.d.ts +1 -1
- package/package.json +1 -1
|
@@ -189,6 +189,26 @@ interface GithubInstallationTokenResponse {
|
|
|
189
189
|
account_login: string;
|
|
190
190
|
account_type: string;
|
|
191
191
|
}
|
|
192
|
+
interface GithubAppInfo {
|
|
193
|
+
slug: string;
|
|
194
|
+
install_url: string;
|
|
195
|
+
}
|
|
196
|
+
interface GithubUserSummary {
|
|
197
|
+
id: number;
|
|
198
|
+
login: string;
|
|
199
|
+
}
|
|
200
|
+
interface GithubUserInstallation {
|
|
201
|
+
id: number;
|
|
202
|
+
html_url: string;
|
|
203
|
+
account_id: number;
|
|
204
|
+
account_login: string;
|
|
205
|
+
account_type: string;
|
|
206
|
+
target_type: string;
|
|
207
|
+
}
|
|
208
|
+
interface GithubUserInstallationsResponse {
|
|
209
|
+
user: GithubUserSummary;
|
|
210
|
+
installations: GithubUserInstallation[];
|
|
211
|
+
}
|
|
192
212
|
interface PkceChallenge {
|
|
193
213
|
verifier: string;
|
|
194
214
|
challenge: string;
|
|
@@ -204,4 +224,4 @@ interface BuildOauthInitUrlOptions {
|
|
|
204
224
|
state?: string;
|
|
205
225
|
}
|
|
206
226
|
|
|
207
|
-
export type { ActivatedDevice as A, BillingPortalResponse as B, Customer as C, EntitlementCustomer as E,
|
|
227
|
+
export type { ActivatedDevice as A, BillingPortalResponse as B, Customer as C, UsagePayload as D, EntitlementCustomer as E, UsageResponse as F, GithubAppInfo as G, LicenseActivatePayload as L, OauthExchangeEntitlement as O, PkceChallenge as P, SignedLicense as S, UsageFeatureState as U, BuildOauthInitUrlOptions as a, EntitlementsResponse as b, GithubInstallationTokenPayload as c, GithubInstallationTokenResponse as d, GithubUserInstallation as e, GithubUserInstallationsResponse as f, GithubUserSummary as g, LicenseActivateResponse as h, LicenseCheckPayload as i, LicenseCheckResponse as j, LicensePublicKey as k, LicensePublicKeysResponse as l, LicenseRefreshPayload as m, LicenseSnapshotPayload as n, LicenseSyncUsagePayload as o, LicenseSyncUsageResponse as p, LicensingMode as q, OauthExchangePayload as r, OauthExchangeResponse as s, OauthProvider as t, OauthProviderInfo as u, OauthProvidersResponse as v, OtpCustomer as w, OtpRequestPayload as x, OtpVerifyPayload as y, OtpVerifyResponse as z };
|
|
@@ -189,6 +189,26 @@ interface GithubInstallationTokenResponse {
|
|
|
189
189
|
account_login: string;
|
|
190
190
|
account_type: string;
|
|
191
191
|
}
|
|
192
|
+
interface GithubAppInfo {
|
|
193
|
+
slug: string;
|
|
194
|
+
install_url: string;
|
|
195
|
+
}
|
|
196
|
+
interface GithubUserSummary {
|
|
197
|
+
id: number;
|
|
198
|
+
login: string;
|
|
199
|
+
}
|
|
200
|
+
interface GithubUserInstallation {
|
|
201
|
+
id: number;
|
|
202
|
+
html_url: string;
|
|
203
|
+
account_id: number;
|
|
204
|
+
account_login: string;
|
|
205
|
+
account_type: string;
|
|
206
|
+
target_type: string;
|
|
207
|
+
}
|
|
208
|
+
interface GithubUserInstallationsResponse {
|
|
209
|
+
user: GithubUserSummary;
|
|
210
|
+
installations: GithubUserInstallation[];
|
|
211
|
+
}
|
|
192
212
|
interface PkceChallenge {
|
|
193
213
|
verifier: string;
|
|
194
214
|
challenge: string;
|
|
@@ -204,4 +224,4 @@ interface BuildOauthInitUrlOptions {
|
|
|
204
224
|
state?: string;
|
|
205
225
|
}
|
|
206
226
|
|
|
207
|
-
export type { ActivatedDevice as A, BillingPortalResponse as B, Customer as C, EntitlementCustomer as E,
|
|
227
|
+
export type { ActivatedDevice as A, BillingPortalResponse as B, Customer as C, UsagePayload as D, EntitlementCustomer as E, UsageResponse as F, GithubAppInfo as G, LicenseActivatePayload as L, OauthExchangeEntitlement as O, PkceChallenge as P, SignedLicense as S, UsageFeatureState as U, BuildOauthInitUrlOptions as a, EntitlementsResponse as b, GithubInstallationTokenPayload as c, GithubInstallationTokenResponse as d, GithubUserInstallation as e, GithubUserInstallationsResponse as f, GithubUserSummary as g, LicenseActivateResponse as h, LicenseCheckPayload as i, LicenseCheckResponse as j, LicensePublicKey as k, LicensePublicKeysResponse as l, LicenseRefreshPayload as m, LicenseSnapshotPayload as n, LicenseSyncUsagePayload as o, LicenseSyncUsageResponse as p, LicensingMode as q, OauthExchangePayload as r, OauthExchangeResponse as s, OauthProvider as t, OauthProviderInfo as u, OauthProvidersResponse as v, OtpCustomer as w, OtpRequestPayload as x, OtpVerifyPayload as y, OtpVerifyResponse as z };
|
package/dist/client.cjs
CHANGED
|
@@ -124,6 +124,9 @@ var BillingClient = class {
|
|
|
124
124
|
payload
|
|
125
125
|
);
|
|
126
126
|
}
|
|
127
|
+
async meGithubInstallations() {
|
|
128
|
+
return this.signed("GET", "/api/me/github/installations");
|
|
129
|
+
}
|
|
127
130
|
async entitlements() {
|
|
128
131
|
return this.signed("GET", "/api/me/entitlements");
|
|
129
132
|
}
|
|
@@ -140,6 +143,9 @@ var BillingClient = class {
|
|
|
140
143
|
async publicLicenseKeys() {
|
|
141
144
|
return this.unsigned("GET", "/api/v1/license-keys/public");
|
|
142
145
|
}
|
|
146
|
+
async githubAppInfo() {
|
|
147
|
+
return this.unsigned("GET", "/api/v1/github/app");
|
|
148
|
+
}
|
|
143
149
|
async signed(method, path, body) {
|
|
144
150
|
const bodyBytes = body === void 0 ? new Uint8Array() : new TextEncoder().encode(JSON.stringify(body));
|
|
145
151
|
const timestamp = Math.floor(Date.now() / 1e3);
|
package/dist/client.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/signature.ts","../src/client.ts"],"names":[],"mappings":";;;AAAO,IAAM,cAAA,GAAiB,iBAAA;AACvB,IAAM,gBAAA,GAAmB,mBAAA;AACzB,IAAM,YAAA,GAAe,eAAA;AACrB,IAAM,gBAAA,GAAmB,mBAAA;AAEhC,eAAe,UAAU,KAAA,EAAoC;AACzD,EAAA,MAAM,SAAS,MAAM,SAAA,EAAU,CAAE,MAAA,CAAO,WAAW,KAAqB,CAAA;AACxE,EAAA,OAAO,WAAA,CAAY,IAAI,UAAA,CAAW,MAAM,CAAC,CAAA;AAC7C;AAEA,SAAS,SAAA,GAA0B;AAC/B,EAAA,MAAM,MAAA,GAAS,WAAW,MAAA,EAAQ,MAAA;AAClC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACT,IAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,EACnF;AACA,EAAA,OAAO,MAAA;AACX;AAEA,SAAS,YAAY,MAAA,EAA4B;AAC7C,EAAA,IAAI,GAAA,GAAM,EAAA;AACV,EAAA,KAAA,MAAW,QAAQ,MAAA,EAAQ;AACvB,IAAA,GAAA,IAAO,KAAK,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AAAA,EAC5C;AACA,EAAA,OAAO,GAAA;AACX;AAEO,SAAS,QAAA,GAAmB;AAC/B,EAAA,MAAM,GAAA,GAAM,IAAI,UAAA,CAAW,EAAE,CAAA;AAC7B,EAAA,IAAI,UAAA,CAAW,QAAQ,eAAA,EAAiB;AACpC,IAAA,UAAA,CAAW,MAAA,CAAO,gBAAgB,GAAG,CAAA;AAAA,EACzC,CAAA,MAAO;AACH,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,MAAA,EAAQ,KAAK,CAAA,EAAG;AACpC,MAAA,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA,CAAK,MAAM,IAAA,CAAK,MAAA,KAAW,GAAG,CAAA;AAAA,IAC3C;AAAA,EACJ;AACA,EAAA,OAAO,YAAY,GAAG,CAAA;AAC1B;AAEA,eAAsB,UAClB,WAAA,EACA,SAAA,EACA,KAAA,EACA,MAAA,EACA,MACA,IAAA,EACe;AACf,EAAA,MAAM,QAAA,GAAW,MAAM,SAAA,CAAU,IAAI,CAAA;AACrC,EAAA,OAAO,GAAG,WAAW;AAAA,EAAK,SAAS;AAAA,EAAK,KAAK;AAAA,EAAK,MAAA,CAAO,aAAa;AAAA,EAAK,IAAI;AAAA,EAAK,QAAQ,CAAA,CAAA;AAChG;AAEA,eAAsB,IAAA,CAAK,eAAuB,eAAA,EAA0C;AACxF,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY,CAAE,OAAO,aAAa,CAAA;AACtD,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,SAAA;AAAA,IACrB,KAAA;AAAA,IACA,OAAA;AAAA,IACA,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAU;AAAA,IAChC,KAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACX;AACA,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,IAAA,CAAK,MAAA,EAAQ,GAAA,EAAK,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,eAAe,CAAiB,CAAA;AACpG,EAAA,OAAO,WAAA,CAAY,IAAI,UAAA,CAAW,GAAG,CAAC,CAAA;AAC1C;;;ACrBO,IAAM,eAAA,GAAN,cAA8B,KAAA,CAAM;AAAA,EACvC,MAAA;AAAA,EACA,IAAA;AAAA,EACA,WAAA,CAAY,QAAgB,IAAA,EAAc;AACtC,IAAA,KAAA,CAAM,CAAA,YAAA,EAAe,MAAM,CAAA,EAAA,EAAK,IAAI,CAAA,CAAE,CAAA;AACtC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EAChB;AACJ;AAEO,IAAM,gBAAN,MAAoB;AAAA,EACN,OAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACT,aAAA;AAAA,EACS,OAAA;AAAA,EAEjB,YAAY,MAAA,EAA6B;AACrC,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC/C,IAAA,IAAA,CAAK,cAAc,MAAA,CAAO,WAAA;AAC1B,IAAA,IAAA,CAAK,gBAAgB,MAAA,CAAO,aAAA;AAC5B,IAAA,IAAA,CAAK,gBAAgB,MAAA,CAAO,aAAA;AAC5B,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA,CAAO,OAAA,IAAW,UAAA,CAAW,KAAA;AAC5C,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACf,MAAA,MAAM,IAAI,MAAM,uFAAuF,CAAA;AAAA,IAC3G;AAAA,EACJ;AAAA,EAEA,iBAAiB,KAAA,EAAqB;AAClC,IAAA,IAAA,CAAK,aAAA,GAAgB,KAAA;AAAA,EACzB;AAAA,EAEA,MAAM,WAAW,OAAA,EAA2C;AACxD,IAAA,MAAM,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,gCAAA,EAAkC,OAAO,CAAA;AAAA,EACvE;AAAA,EAEA,MAAM,UAAU,OAAA,EAAuD;AACnE,IAAA,MAAM,MAAM,MAAM,IAAA,CAAK,MAAA,CAA0B,MAAA,EAAQ,iCAAiC,OAAO,CAAA;AACjG,IAAA,IAAA,CAAK,gBAAA,CAAiB,IAAI,YAAY,CAAA;AACtC,IAAA,OAAO,GAAA;AAAA,EACX;AAAA,EAEA,MAAM,UAAA,GAAgC;AAClC,IAAA,OAAO,IAAA,CAAK,MAAA,CAAiB,KAAA,EAAO,SAAS,CAAA;AAAA,EACjD;AAAA,EAEA,MAAM,aAAa,OAAA,EAA6D;AAC5E,IAAA,OAAO,IAAA,CAAK,MAAA,CAA6B,MAAA,EAAQ,qBAAA,EAAuB,OAAO,CAAA;AAAA,EACnF;AAAA,EAEA,MAAM,gBAAgB,OAAA,EAAmE;AACrF,IAAA,OAAO,IAAA,CAAK,MAAA,CAAgC,MAAA,EAAQ,wBAAA,EAA0B,OAAO,CAAA;AAAA,EACzF;AAAA,EAEA,MAAM,eAAe,OAAA,EAAkE;AACnF,IAAA,OAAO,IAAA,CAAK,MAAA,CAAgC,MAAA,EAAQ,uBAAA,EAAyB,OAAO,CAAA;AAAA,EACxF;AAAA,EAEA,MAAM,iBAAiB,OAAA,EAAqE;AACxF,IAAA,OAAO,IAAA,CAAK,MAAA,CAAiC,MAAA,EAAQ,0BAAA,EAA4B,OAAO,CAAA;AAAA,EAC5F;AAAA,EAEA,MAAM,mBAAmB,OAAA,EAAkD;AACvE,IAAA,OAAO,KAAK,MAAA,CAA+B,KAAA,EAAO,oBAAoB,kBAAA,CAAmB,OAAO,CAAC,CAAA,eAAA,CAAiB,CAAA;AAAA,EACtH;AAAA,EAEA,MAAM,kBAAkB,OAAA,EAA+D;AACnF,IAAA,MAAM,MAAM,MAAM,IAAA,CAAK,MAAA,CAA8B,MAAA,EAAQ,4BAA4B,OAAO,CAAA;AAChG,IAAA,IAAA,CAAK,gBAAA,CAAiB,IAAI,YAAY,CAAA;AACtC,IAAA,OAAO,GAAA;AAAA,EACX;AAAA,EAEA,MAAM,uBAAA,CACF,OAAA,GAA0C,EAAC,EACH;AACxC,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MACR,MAAA;AAAA,MACA,mCAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAAA,EAEA,MAAM,YAAA,GAA8C;AAChD,IAAA,OAAO,IAAA,CAAK,MAAA,CAA6B,KAAA,EAAO,sBAAsB,CAAA;AAAA,EAC1E;AAAA,EAEA,MAAM,cAAc,SAAA,EAAmD;AACnE,IAAA,MAAM,IAAA,GAAO,CAAA,+BAAA,EAAkC,kBAAA,CAAmB,SAAS,CAAC,CAAA,CAAA;AAC5E,IAAA,OAAO,IAAA,CAAK,MAAA,CAA8B,KAAA,EAAO,IAAI,CAAA;AAAA,EACzD;AAAA,EAEA,MAAM,WAAW,OAAA,EAA+C;AAC5D,IAAA,OAAO,IAAA,CAAK,MAAA,CAAsB,MAAA,EAAQ,eAAA,EAAiB,OAAO,CAAA;AAAA,EACtE;AAAA,EAEA,MAAM,oBAAoB,OAAA,EAA+C;AACrE,IAAA,OAAO,IAAA,CAAK,MAAA,CAAsB,MAAA,EAAQ,yBAAA,EAA2B,OAAO,CAAA;AAAA,EAChF;AAAA,EAEA,MAAM,iBAAA,GAAwD;AAC1D,IAAA,OAAO,IAAA,CAAK,QAAA,CAAoC,KAAA,EAAO,6BAA6B,CAAA;AAAA,EACxF;AAAA,EAEA,MAAc,MAAA,CAAoB,MAAA,EAAgB,IAAA,EAAc,IAAA,EAA4B;AACxF,IAAA,MAAM,SAAA,GAAY,IAAA,KAAS,MAAA,GAAY,IAAI,UAAA,EAAW,GAAI,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA;AACvG,IAAA,MAAM,YAAY,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AAC9C,IAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,IAAA,MAAM,eAAA,GAAkB,MAAM,SAAA,CAAU,IAAA,CAAK,aAAa,SAAA,EAAW,KAAA,EAAO,MAAA,EAAQ,IAAA,EAAM,SAAS,CAAA;AACnG,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,IAAA,CAAK,eAAe,eAAe,CAAA;AAEhE,IAAA,MAAM,OAAA,GAAkC;AAAA,MACpC,MAAA,EAAQ,kBAAA;AAAA,MACR,CAAC,cAAc,GAAG,IAAA,CAAK,WAAA;AAAA,MACvB,CAAC,gBAAgB,GAAG,MAAA,CAAO,SAAS,CAAA;AAAA,MACpC,CAAC,YAAY,GAAG,KAAA;AAAA,MAChB,CAAC,gBAAgB,GAAG;AAAA,KACxB;AACA,IAAA,IAAI,SAAA,CAAU,MAAA,GAAS,CAAA,EAAG,OAAA,CAAQ,cAAc,CAAA,GAAI,kBAAA;AACpD,IAAA,IAAI,KAAK,aAAA,EAAe,OAAA,CAAQ,aAAA,GAAgB,CAAA,OAAA,EAAU,KAAK,aAAa,CAAA,CAAA;AAE5E,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAG,IAAA,CAAK,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI;AAAA,MACrD,MAAA;AAAA,MACA,OAAA;AAAA,MACA,IAAA,EAAM,SAAA,CAAU,MAAA,GAAS,CAAA,GAAI,SAAA,GAAY;AAAA,KAC5C,CAAA;AAED,IAAA,OAAO,IAAA,CAAK,cAAiB,GAAG,CAAA;AAAA,EACpC;AAAA,EAEA,MAAc,QAAA,CAAsB,MAAA,EAAgB,IAAA,EAAc,IAAA,EAA4B;AAC1F,IAAA,MAAM,OAAA,GAAkC,EAAE,MAAA,EAAQ,kBAAA,EAAmB;AACrE,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI,SAAS,MAAA,EAAW;AACpB,MAAA,OAAA,CAAQ,cAAc,CAAA,GAAI,kBAAA;AAC1B,MAAA,QAAA,GAAW,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA,IAClC;AAEA,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAG,IAAA,CAAK,OAAO,CAAA,EAAG,IAAI,IAAI,EAAE,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM,UAAU,CAAA;AAC5F,IAAA,OAAO,IAAA,CAAK,cAAiB,GAAG,CAAA;AAAA,EACpC;AAAA,EAEA,MAAc,cAAiB,GAAA,EAA2B;AACtD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACT,MAAA,IAAI,IAAA;AACJ,MAAA,IAAI;AACA,QAAA,MAAM,MAAA,GAAU,MAAM,GAAA,CAAI,IAAA,EAAK;AAC/B,QAAA,IAAA,GAAO,QAAQ,KAAA,IAAS,EAAA;AAAA,MAC5B,CAAA,CAAA,MAAQ;AACJ,QAAA,IAAI;AACA,UAAA,IAAA,GAAO,MAAM,IAAI,IAAA,EAAK;AAAA,QAC1B,CAAA,CAAA,MAAQ;AACJ,UAAA,IAAA,GAAO,EAAA;AAAA,QACX;AAAA,MACJ;AACA,MAAA,MAAM,IAAI,eAAA,CAAgB,GAAA,CAAI,MAAA,EAAQ,IAAI,CAAA;AAAA,IAC9C;AAEA,IAAA,IAAI,GAAA,CAAI,WAAW,GAAA,EAAK;AACpB,MAAA,OAAO,MAAA;AAAA,IACX;AAEA,IAAA,OAAQ,MAAM,IAAI,IAAA,EAAK;AAAA,EAC3B;AACJ","file":"client.cjs","sourcesContent":["export const HEADER_PRODUCT = 'X-Akira-Product';\nexport const HEADER_TIMESTAMP = 'X-Akira-Timestamp';\nexport const HEADER_NONCE = 'X-Akira-Nonce';\nexport const HEADER_SIGNATURE = 'X-Akira-Signature';\n\nasync function sha256Hex(bytes: Uint8Array): Promise<string> {\n const digest = await getSubtle().digest('SHA-256', bytes as BufferSource);\n return bufferToHex(new Uint8Array(digest));\n}\n\nfunction getSubtle(): SubtleCrypto {\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) {\n throw new Error('Web Crypto SubtleCrypto API is not available in this runtime.');\n }\n return subtle;\n}\n\nfunction bufferToHex(buffer: Uint8Array): string {\n let out = '';\n for (const byte of buffer) {\n out += byte.toString(16).padStart(2, '0');\n }\n return out;\n}\n\nexport function newNonce(): string {\n const buf = new Uint8Array(16);\n if (globalThis.crypto?.getRandomValues) {\n globalThis.crypto.getRandomValues(buf);\n } else {\n for (let i = 0; i < buf.length; i += 1) {\n buf[i] = Math.floor(Math.random() * 256);\n }\n }\n return bufferToHex(buf);\n}\n\nexport async function canonical(\n productSlug: string,\n timestamp: number,\n nonce: string,\n method: string,\n path: string,\n body: Uint8Array,\n): Promise<string> {\n const bodyHash = await sha256Hex(body);\n return `${productSlug}\\n${timestamp}\\n${nonce}\\n${method.toUpperCase()}\\n${path}\\n${bodyHash}`;\n}\n\nexport async function sign(productSecret: string, canonicalString: string): Promise<string> {\n const subtle = getSubtle();\n const keyData = new TextEncoder().encode(productSecret) as BufferSource;\n const key = await subtle.importKey(\n 'raw',\n keyData,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n const sig = await subtle.sign('HMAC', key, new TextEncoder().encode(canonicalString) as BufferSource);\n return bufferToHex(new Uint8Array(sig));\n}\n","import {\n HEADER_NONCE,\n HEADER_PRODUCT,\n HEADER_SIGNATURE,\n HEADER_TIMESTAMP,\n canonical,\n newNonce,\n sign,\n} from './signature';\nimport type {\n BillingPortalResponse,\n Customer,\n EntitlementsResponse,\n LicenseActivatePayload,\n LicenseActivateResponse,\n LicenseCheckPayload,\n LicenseCheckResponse,\n LicensePublicKeysResponse,\n LicenseRefreshPayload,\n LicenseSyncUsagePayload,\n LicenseSyncUsageResponse,\n GithubInstallationTokenPayload,\n GithubInstallationTokenResponse,\n OauthExchangePayload,\n OauthExchangeResponse,\n OauthProvidersResponse,\n OtpRequestPayload,\n OtpVerifyPayload,\n OtpVerifyResponse,\n UsagePayload,\n UsageResponse,\n} from './client-types';\n\nexport interface BillingClientConfig {\n baseUrl: string;\n productSlug: string;\n productSecret: string;\n customerToken?: string;\n fetcher?: typeof fetch;\n}\n\nexport class BillingApiError extends Error {\n status: number;\n code: string;\n constructor(status: number, code: string) {\n super(`billing api ${status}: ${code}`);\n this.status = status;\n this.code = code;\n }\n}\n\nexport class BillingClient {\n private readonly baseUrl: string;\n private readonly productSlug: string;\n private readonly productSecret: string;\n private customerToken: string | undefined;\n private readonly fetcher: typeof fetch;\n\n constructor(config: BillingClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.productSlug = config.productSlug;\n this.productSecret = config.productSecret;\n this.customerToken = config.customerToken;\n this.fetcher = config.fetcher ?? globalThis.fetch;\n if (!this.fetcher) {\n throw new Error('No fetch implementation available. Pass `fetcher` or use a runtime with global fetch.');\n }\n }\n\n setCustomerToken(token: string): void {\n this.customerToken = token;\n }\n\n async requestOtp(payload: OtpRequestPayload): Promise<void> {\n await this.signed('POST', '/api/auth/customer/otp/request', payload);\n }\n\n async verifyOtp(payload: OtpVerifyPayload): Promise<OtpVerifyResponse> {\n const res = await this.signed<OtpVerifyResponse>('POST', '/api/auth/customer/otp/verify', payload);\n this.setCustomerToken(res.access_token);\n return res;\n }\n\n async customerMe(): Promise<Customer> {\n return this.signed<Customer>('GET', '/api/me');\n }\n\n async licenseCheck(payload: LicenseCheckPayload): Promise<LicenseCheckResponse> {\n return this.signed<LicenseCheckResponse>('POST', '/api/licenses/check', payload);\n }\n\n async licenseActivate(payload: LicenseActivatePayload): Promise<LicenseActivateResponse> {\n return this.signed<LicenseActivateResponse>('POST', '/api/licenses/activate', payload);\n }\n\n async licenseRefresh(payload: LicenseRefreshPayload): Promise<LicenseActivateResponse> {\n return this.signed<LicenseActivateResponse>('POST', '/api/licenses/refresh', payload);\n }\n\n async licenseSyncUsage(payload: LicenseSyncUsagePayload): Promise<LicenseSyncUsageResponse> {\n return this.signed<LicenseSyncUsageResponse>('POST', '/api/licenses/sync-usage', payload);\n }\n\n async listOauthProviders(product: string): Promise<OauthProvidersResponse> {\n return this.signed<OauthProvidersResponse>('GET', `/api/v1/products/${encodeURIComponent(product)}/auth/providers`);\n }\n\n async exchangeOauthCode(payload: OauthExchangePayload): Promise<OauthExchangeResponse> {\n const res = await this.signed<OauthExchangeResponse>('POST', '/api/auth/oauth/exchange', payload);\n this.setCustomerToken(res.access_token);\n return res;\n }\n\n async githubInstallationToken(\n payload: GithubInstallationTokenPayload = {},\n ): Promise<GithubInstallationTokenResponse> {\n return this.signed<GithubInstallationTokenResponse>(\n 'POST',\n '/api/me/github/installation-token',\n payload,\n );\n }\n\n async entitlements(): Promise<EntitlementsResponse> {\n return this.signed<EntitlementsResponse>('GET', '/api/me/entitlements');\n }\n\n async billingPortal(returnUrl: string): Promise<BillingPortalResponse> {\n const path = `/api/billing/portal?return_url=${encodeURIComponent(returnUrl)}`;\n return this.signed<BillingPortalResponse>('GET', path);\n }\n\n async trackUsage(payload: UsagePayload): Promise<UsageResponse> {\n return this.signed<UsageResponse>('POST', '/api/me/usage', payload);\n }\n\n async trackAnonymousUsage(payload: UsagePayload): Promise<UsageResponse> {\n return this.signed<UsageResponse>('POST', '/api/v1/usage/anonymous', payload);\n }\n\n async publicLicenseKeys(): Promise<LicensePublicKeysResponse> {\n return this.unsigned<LicensePublicKeysResponse>('GET', '/api/v1/license-keys/public');\n }\n\n private async signed<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const bodyBytes = body === undefined ? new Uint8Array() : new TextEncoder().encode(JSON.stringify(body));\n const timestamp = Math.floor(Date.now() / 1000);\n const nonce = newNonce();\n const canonicalString = await canonical(this.productSlug, timestamp, nonce, method, path, bodyBytes);\n const signature = await sign(this.productSecret, canonicalString);\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n [HEADER_PRODUCT]: this.productSlug,\n [HEADER_TIMESTAMP]: String(timestamp),\n [HEADER_NONCE]: nonce,\n [HEADER_SIGNATURE]: signature,\n };\n if (bodyBytes.length > 0) headers['Content-Type'] = 'application/json';\n if (this.customerToken) headers.Authorization = `Bearer ${this.customerToken}`;\n\n const res = await this.fetcher(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: bodyBytes.length > 0 ? bodyBytes : undefined,\n });\n\n return this.parseResponse<T>(res);\n }\n\n private async unsigned<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const headers: Record<string, string> = { Accept: 'application/json' };\n let bodyInit: BodyInit | undefined;\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json';\n bodyInit = JSON.stringify(body);\n }\n\n const res = await this.fetcher(`${this.baseUrl}${path}`, { method, headers, body: bodyInit });\n return this.parseResponse<T>(res);\n }\n\n private async parseResponse<T>(res: Response): Promise<T> {\n if (!res.ok) {\n let code: string;\n try {\n const parsed = (await res.json()) as { error?: string };\n code = parsed?.error ?? '';\n } catch {\n try {\n code = await res.text();\n } catch {\n code = '';\n }\n }\n throw new BillingApiError(res.status, code);\n }\n\n if (res.status === 204) {\n return undefined as T;\n }\n\n return (await res.json()) as T;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/signature.ts","../src/client.ts"],"names":[],"mappings":"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","file":"client.cjs","sourcesContent":["export const HEADER_PRODUCT = 'X-Akira-Product';\nexport const HEADER_TIMESTAMP = 'X-Akira-Timestamp';\nexport const HEADER_NONCE = 'X-Akira-Nonce';\nexport const HEADER_SIGNATURE = 'X-Akira-Signature';\n\nasync function sha256Hex(bytes: Uint8Array): Promise<string> {\n const digest = await getSubtle().digest('SHA-256', bytes as BufferSource);\n return bufferToHex(new Uint8Array(digest));\n}\n\nfunction getSubtle(): SubtleCrypto {\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) {\n throw new Error('Web Crypto SubtleCrypto API is not available in this runtime.');\n }\n return subtle;\n}\n\nfunction bufferToHex(buffer: Uint8Array): string {\n let out = '';\n for (const byte of buffer) {\n out += byte.toString(16).padStart(2, '0');\n }\n return out;\n}\n\nexport function newNonce(): string {\n const buf = new Uint8Array(16);\n if (globalThis.crypto?.getRandomValues) {\n globalThis.crypto.getRandomValues(buf);\n } else {\n for (let i = 0; i < buf.length; i += 1) {\n buf[i] = Math.floor(Math.random() * 256);\n }\n }\n return bufferToHex(buf);\n}\n\nexport async function canonical(\n productSlug: string,\n timestamp: number,\n nonce: string,\n method: string,\n path: string,\n body: Uint8Array,\n): Promise<string> {\n const bodyHash = await sha256Hex(body);\n return `${productSlug}\\n${timestamp}\\n${nonce}\\n${method.toUpperCase()}\\n${path}\\n${bodyHash}`;\n}\n\nexport async function sign(productSecret: string, canonicalString: string): Promise<string> {\n const subtle = getSubtle();\n const keyData = new TextEncoder().encode(productSecret) as BufferSource;\n const key = await subtle.importKey(\n 'raw',\n keyData,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n const sig = await subtle.sign('HMAC', key, new TextEncoder().encode(canonicalString) as BufferSource);\n return bufferToHex(new Uint8Array(sig));\n}\n","import {\n HEADER_NONCE,\n HEADER_PRODUCT,\n HEADER_SIGNATURE,\n HEADER_TIMESTAMP,\n canonical,\n newNonce,\n sign,\n} from './signature';\nimport type {\n BillingPortalResponse,\n Customer,\n EntitlementsResponse,\n LicenseActivatePayload,\n LicenseActivateResponse,\n LicenseCheckPayload,\n LicenseCheckResponse,\n LicensePublicKeysResponse,\n LicenseRefreshPayload,\n LicenseSyncUsagePayload,\n LicenseSyncUsageResponse,\n GithubAppInfo,\n GithubInstallationTokenPayload,\n GithubInstallationTokenResponse,\n GithubUserInstallationsResponse,\n OauthExchangePayload,\n OauthExchangeResponse,\n OauthProvidersResponse,\n OtpRequestPayload,\n OtpVerifyPayload,\n OtpVerifyResponse,\n UsagePayload,\n UsageResponse,\n} from './client-types';\n\nexport interface BillingClientConfig {\n baseUrl: string;\n productSlug: string;\n productSecret: string;\n customerToken?: string;\n fetcher?: typeof fetch;\n}\n\nexport class BillingApiError extends Error {\n status: number;\n code: string;\n constructor(status: number, code: string) {\n super(`billing api ${status}: ${code}`);\n this.status = status;\n this.code = code;\n }\n}\n\nexport class BillingClient {\n private readonly baseUrl: string;\n private readonly productSlug: string;\n private readonly productSecret: string;\n private customerToken: string | undefined;\n private readonly fetcher: typeof fetch;\n\n constructor(config: BillingClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.productSlug = config.productSlug;\n this.productSecret = config.productSecret;\n this.customerToken = config.customerToken;\n this.fetcher = config.fetcher ?? globalThis.fetch;\n if (!this.fetcher) {\n throw new Error('No fetch implementation available. Pass `fetcher` or use a runtime with global fetch.');\n }\n }\n\n setCustomerToken(token: string): void {\n this.customerToken = token;\n }\n\n async requestOtp(payload: OtpRequestPayload): Promise<void> {\n await this.signed('POST', '/api/auth/customer/otp/request', payload);\n }\n\n async verifyOtp(payload: OtpVerifyPayload): Promise<OtpVerifyResponse> {\n const res = await this.signed<OtpVerifyResponse>('POST', '/api/auth/customer/otp/verify', payload);\n this.setCustomerToken(res.access_token);\n return res;\n }\n\n async customerMe(): Promise<Customer> {\n return this.signed<Customer>('GET', '/api/me');\n }\n\n async licenseCheck(payload: LicenseCheckPayload): Promise<LicenseCheckResponse> {\n return this.signed<LicenseCheckResponse>('POST', '/api/licenses/check', payload);\n }\n\n async licenseActivate(payload: LicenseActivatePayload): Promise<LicenseActivateResponse> {\n return this.signed<LicenseActivateResponse>('POST', '/api/licenses/activate', payload);\n }\n\n async licenseRefresh(payload: LicenseRefreshPayload): Promise<LicenseActivateResponse> {\n return this.signed<LicenseActivateResponse>('POST', '/api/licenses/refresh', payload);\n }\n\n async licenseSyncUsage(payload: LicenseSyncUsagePayload): Promise<LicenseSyncUsageResponse> {\n return this.signed<LicenseSyncUsageResponse>('POST', '/api/licenses/sync-usage', payload);\n }\n\n async listOauthProviders(product: string): Promise<OauthProvidersResponse> {\n return this.signed<OauthProvidersResponse>('GET', `/api/v1/products/${encodeURIComponent(product)}/auth/providers`);\n }\n\n async exchangeOauthCode(payload: OauthExchangePayload): Promise<OauthExchangeResponse> {\n const res = await this.signed<OauthExchangeResponse>('POST', '/api/auth/oauth/exchange', payload);\n this.setCustomerToken(res.access_token);\n return res;\n }\n\n async githubInstallationToken(\n payload: GithubInstallationTokenPayload = {},\n ): Promise<GithubInstallationTokenResponse> {\n return this.signed<GithubInstallationTokenResponse>(\n 'POST',\n '/api/me/github/installation-token',\n payload,\n );\n }\n\n async meGithubInstallations(): Promise<GithubUserInstallationsResponse> {\n return this.signed<GithubUserInstallationsResponse>('GET', '/api/me/github/installations');\n }\n\n async entitlements(): Promise<EntitlementsResponse> {\n return this.signed<EntitlementsResponse>('GET', '/api/me/entitlements');\n }\n\n async billingPortal(returnUrl: string): Promise<BillingPortalResponse> {\n const path = `/api/billing/portal?return_url=${encodeURIComponent(returnUrl)}`;\n return this.signed<BillingPortalResponse>('GET', path);\n }\n\n async trackUsage(payload: UsagePayload): Promise<UsageResponse> {\n return this.signed<UsageResponse>('POST', '/api/me/usage', payload);\n }\n\n async trackAnonymousUsage(payload: UsagePayload): Promise<UsageResponse> {\n return this.signed<UsageResponse>('POST', '/api/v1/usage/anonymous', payload);\n }\n\n async publicLicenseKeys(): Promise<LicensePublicKeysResponse> {\n return this.unsigned<LicensePublicKeysResponse>('GET', '/api/v1/license-keys/public');\n }\n\n async githubAppInfo(): Promise<GithubAppInfo> {\n return this.unsigned<GithubAppInfo>('GET', '/api/v1/github/app');\n }\n\n private async signed<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const bodyBytes = body === undefined ? new Uint8Array() : new TextEncoder().encode(JSON.stringify(body));\n const timestamp = Math.floor(Date.now() / 1000);\n const nonce = newNonce();\n const canonicalString = await canonical(this.productSlug, timestamp, nonce, method, path, bodyBytes);\n const signature = await sign(this.productSecret, canonicalString);\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n [HEADER_PRODUCT]: this.productSlug,\n [HEADER_TIMESTAMP]: String(timestamp),\n [HEADER_NONCE]: nonce,\n [HEADER_SIGNATURE]: signature,\n };\n if (bodyBytes.length > 0) headers['Content-Type'] = 'application/json';\n if (this.customerToken) headers.Authorization = `Bearer ${this.customerToken}`;\n\n const res = await this.fetcher(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: bodyBytes.length > 0 ? bodyBytes : undefined,\n });\n\n return this.parseResponse<T>(res);\n }\n\n private async unsigned<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const headers: Record<string, string> = { Accept: 'application/json' };\n let bodyInit: BodyInit | undefined;\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json';\n bodyInit = JSON.stringify(body);\n }\n\n const res = await this.fetcher(`${this.baseUrl}${path}`, { method, headers, body: bodyInit });\n return this.parseResponse<T>(res);\n }\n\n private async parseResponse<T>(res: Response): Promise<T> {\n if (!res.ok) {\n let code: string;\n try {\n const parsed = (await res.json()) as { error?: string };\n code = parsed?.error ?? '';\n } catch {\n try {\n code = await res.text();\n } catch {\n code = '';\n }\n }\n throw new BillingApiError(res.status, code);\n }\n\n if (res.status === 204) {\n return undefined as T;\n }\n\n return (await res.json()) as T;\n }\n}\n"]}
|
package/dist/client.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { x as OtpRequestPayload, y as OtpVerifyPayload, z as OtpVerifyResponse, C as Customer, i as LicenseCheckPayload, j as LicenseCheckResponse, L as LicenseActivatePayload, h as LicenseActivateResponse, m as LicenseRefreshPayload, o as LicenseSyncUsagePayload, p as LicenseSyncUsageResponse, v as OauthProvidersResponse, r as OauthExchangePayload, s as OauthExchangeResponse, c as GithubInstallationTokenPayload, d as GithubInstallationTokenResponse, f as GithubUserInstallationsResponse, b as EntitlementsResponse, B as BillingPortalResponse, D as UsagePayload, F as UsageResponse, l as LicensePublicKeysResponse, G as GithubAppInfo } from './client-types-CtRkHWna.cjs';
|
|
2
2
|
|
|
3
3
|
interface BillingClientConfig {
|
|
4
4
|
baseUrl: string;
|
|
@@ -30,11 +30,13 @@ declare class BillingClient {
|
|
|
30
30
|
listOauthProviders(product: string): Promise<OauthProvidersResponse>;
|
|
31
31
|
exchangeOauthCode(payload: OauthExchangePayload): Promise<OauthExchangeResponse>;
|
|
32
32
|
githubInstallationToken(payload?: GithubInstallationTokenPayload): Promise<GithubInstallationTokenResponse>;
|
|
33
|
+
meGithubInstallations(): Promise<GithubUserInstallationsResponse>;
|
|
33
34
|
entitlements(): Promise<EntitlementsResponse>;
|
|
34
35
|
billingPortal(returnUrl: string): Promise<BillingPortalResponse>;
|
|
35
36
|
trackUsage(payload: UsagePayload): Promise<UsageResponse>;
|
|
36
37
|
trackAnonymousUsage(payload: UsagePayload): Promise<UsageResponse>;
|
|
37
38
|
publicLicenseKeys(): Promise<LicensePublicKeysResponse>;
|
|
39
|
+
githubAppInfo(): Promise<GithubAppInfo>;
|
|
38
40
|
private signed;
|
|
39
41
|
private unsigned;
|
|
40
42
|
private parseResponse;
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { x as OtpRequestPayload, y as OtpVerifyPayload, z as OtpVerifyResponse, C as Customer, i as LicenseCheckPayload, j as LicenseCheckResponse, L as LicenseActivatePayload, h as LicenseActivateResponse, m as LicenseRefreshPayload, o as LicenseSyncUsagePayload, p as LicenseSyncUsageResponse, v as OauthProvidersResponse, r as OauthExchangePayload, s as OauthExchangeResponse, c as GithubInstallationTokenPayload, d as GithubInstallationTokenResponse, f as GithubUserInstallationsResponse, b as EntitlementsResponse, B as BillingPortalResponse, D as UsagePayload, F as UsageResponse, l as LicensePublicKeysResponse, G as GithubAppInfo } from './client-types-CtRkHWna.js';
|
|
2
2
|
|
|
3
3
|
interface BillingClientConfig {
|
|
4
4
|
baseUrl: string;
|
|
@@ -30,11 +30,13 @@ declare class BillingClient {
|
|
|
30
30
|
listOauthProviders(product: string): Promise<OauthProvidersResponse>;
|
|
31
31
|
exchangeOauthCode(payload: OauthExchangePayload): Promise<OauthExchangeResponse>;
|
|
32
32
|
githubInstallationToken(payload?: GithubInstallationTokenPayload): Promise<GithubInstallationTokenResponse>;
|
|
33
|
+
meGithubInstallations(): Promise<GithubUserInstallationsResponse>;
|
|
33
34
|
entitlements(): Promise<EntitlementsResponse>;
|
|
34
35
|
billingPortal(returnUrl: string): Promise<BillingPortalResponse>;
|
|
35
36
|
trackUsage(payload: UsagePayload): Promise<UsageResponse>;
|
|
36
37
|
trackAnonymousUsage(payload: UsagePayload): Promise<UsageResponse>;
|
|
37
38
|
publicLicenseKeys(): Promise<LicensePublicKeysResponse>;
|
|
39
|
+
githubAppInfo(): Promise<GithubAppInfo>;
|
|
38
40
|
private signed;
|
|
39
41
|
private unsigned;
|
|
40
42
|
private parseResponse;
|
package/dist/client.js
CHANGED
|
@@ -122,6 +122,9 @@ var BillingClient = class {
|
|
|
122
122
|
payload
|
|
123
123
|
);
|
|
124
124
|
}
|
|
125
|
+
async meGithubInstallations() {
|
|
126
|
+
return this.signed("GET", "/api/me/github/installations");
|
|
127
|
+
}
|
|
125
128
|
async entitlements() {
|
|
126
129
|
return this.signed("GET", "/api/me/entitlements");
|
|
127
130
|
}
|
|
@@ -138,6 +141,9 @@ var BillingClient = class {
|
|
|
138
141
|
async publicLicenseKeys() {
|
|
139
142
|
return this.unsigned("GET", "/api/v1/license-keys/public");
|
|
140
143
|
}
|
|
144
|
+
async githubAppInfo() {
|
|
145
|
+
return this.unsigned("GET", "/api/v1/github/app");
|
|
146
|
+
}
|
|
141
147
|
async signed(method, path, body) {
|
|
142
148
|
const bodyBytes = body === void 0 ? new Uint8Array() : new TextEncoder().encode(JSON.stringify(body));
|
|
143
149
|
const timestamp = Math.floor(Date.now() / 1e3);
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/signature.ts","../src/client.ts"],"names":[],"mappings":"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","file":"client.js","sourcesContent":["export const HEADER_PRODUCT = 'X-Akira-Product';\nexport const HEADER_TIMESTAMP = 'X-Akira-Timestamp';\nexport const HEADER_NONCE = 'X-Akira-Nonce';\nexport const HEADER_SIGNATURE = 'X-Akira-Signature';\n\nasync function sha256Hex(bytes: Uint8Array): Promise<string> {\n const digest = await getSubtle().digest('SHA-256', bytes as BufferSource);\n return bufferToHex(new Uint8Array(digest));\n}\n\nfunction getSubtle(): SubtleCrypto {\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) {\n throw new Error('Web Crypto SubtleCrypto API is not available in this runtime.');\n }\n return subtle;\n}\n\nfunction bufferToHex(buffer: Uint8Array): string {\n let out = '';\n for (const byte of buffer) {\n out += byte.toString(16).padStart(2, '0');\n }\n return out;\n}\n\nexport function newNonce(): string {\n const buf = new Uint8Array(16);\n if (globalThis.crypto?.getRandomValues) {\n globalThis.crypto.getRandomValues(buf);\n } else {\n for (let i = 0; i < buf.length; i += 1) {\n buf[i] = Math.floor(Math.random() * 256);\n }\n }\n return bufferToHex(buf);\n}\n\nexport async function canonical(\n productSlug: string,\n timestamp: number,\n nonce: string,\n method: string,\n path: string,\n body: Uint8Array,\n): Promise<string> {\n const bodyHash = await sha256Hex(body);\n return `${productSlug}\\n${timestamp}\\n${nonce}\\n${method.toUpperCase()}\\n${path}\\n${bodyHash}`;\n}\n\nexport async function sign(productSecret: string, canonicalString: string): Promise<string> {\n const subtle = getSubtle();\n const keyData = new TextEncoder().encode(productSecret) as BufferSource;\n const key = await subtle.importKey(\n 'raw',\n keyData,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n const sig = await subtle.sign('HMAC', key, new TextEncoder().encode(canonicalString) as BufferSource);\n return bufferToHex(new Uint8Array(sig));\n}\n","import {\n HEADER_NONCE,\n HEADER_PRODUCT,\n HEADER_SIGNATURE,\n HEADER_TIMESTAMP,\n canonical,\n newNonce,\n sign,\n} from './signature';\nimport type {\n BillingPortalResponse,\n Customer,\n EntitlementsResponse,\n LicenseActivatePayload,\n LicenseActivateResponse,\n LicenseCheckPayload,\n LicenseCheckResponse,\n LicensePublicKeysResponse,\n LicenseRefreshPayload,\n LicenseSyncUsagePayload,\n LicenseSyncUsageResponse,\n GithubInstallationTokenPayload,\n GithubInstallationTokenResponse,\n OauthExchangePayload,\n OauthExchangeResponse,\n OauthProvidersResponse,\n OtpRequestPayload,\n OtpVerifyPayload,\n OtpVerifyResponse,\n UsagePayload,\n UsageResponse,\n} from './client-types';\n\nexport interface BillingClientConfig {\n baseUrl: string;\n productSlug: string;\n productSecret: string;\n customerToken?: string;\n fetcher?: typeof fetch;\n}\n\nexport class BillingApiError extends Error {\n status: number;\n code: string;\n constructor(status: number, code: string) {\n super(`billing api ${status}: ${code}`);\n this.status = status;\n this.code = code;\n }\n}\n\nexport class BillingClient {\n private readonly baseUrl: string;\n private readonly productSlug: string;\n private readonly productSecret: string;\n private customerToken: string | undefined;\n private readonly fetcher: typeof fetch;\n\n constructor(config: BillingClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.productSlug = config.productSlug;\n this.productSecret = config.productSecret;\n this.customerToken = config.customerToken;\n this.fetcher = config.fetcher ?? globalThis.fetch;\n if (!this.fetcher) {\n throw new Error('No fetch implementation available. Pass `fetcher` or use a runtime with global fetch.');\n }\n }\n\n setCustomerToken(token: string): void {\n this.customerToken = token;\n }\n\n async requestOtp(payload: OtpRequestPayload): Promise<void> {\n await this.signed('POST', '/api/auth/customer/otp/request', payload);\n }\n\n async verifyOtp(payload: OtpVerifyPayload): Promise<OtpVerifyResponse> {\n const res = await this.signed<OtpVerifyResponse>('POST', '/api/auth/customer/otp/verify', payload);\n this.setCustomerToken(res.access_token);\n return res;\n }\n\n async customerMe(): Promise<Customer> {\n return this.signed<Customer>('GET', '/api/me');\n }\n\n async licenseCheck(payload: LicenseCheckPayload): Promise<LicenseCheckResponse> {\n return this.signed<LicenseCheckResponse>('POST', '/api/licenses/check', payload);\n }\n\n async licenseActivate(payload: LicenseActivatePayload): Promise<LicenseActivateResponse> {\n return this.signed<LicenseActivateResponse>('POST', '/api/licenses/activate', payload);\n }\n\n async licenseRefresh(payload: LicenseRefreshPayload): Promise<LicenseActivateResponse> {\n return this.signed<LicenseActivateResponse>('POST', '/api/licenses/refresh', payload);\n }\n\n async licenseSyncUsage(payload: LicenseSyncUsagePayload): Promise<LicenseSyncUsageResponse> {\n return this.signed<LicenseSyncUsageResponse>('POST', '/api/licenses/sync-usage', payload);\n }\n\n async listOauthProviders(product: string): Promise<OauthProvidersResponse> {\n return this.signed<OauthProvidersResponse>('GET', `/api/v1/products/${encodeURIComponent(product)}/auth/providers`);\n }\n\n async exchangeOauthCode(payload: OauthExchangePayload): Promise<OauthExchangeResponse> {\n const res = await this.signed<OauthExchangeResponse>('POST', '/api/auth/oauth/exchange', payload);\n this.setCustomerToken(res.access_token);\n return res;\n }\n\n async githubInstallationToken(\n payload: GithubInstallationTokenPayload = {},\n ): Promise<GithubInstallationTokenResponse> {\n return this.signed<GithubInstallationTokenResponse>(\n 'POST',\n '/api/me/github/installation-token',\n payload,\n );\n }\n\n async entitlements(): Promise<EntitlementsResponse> {\n return this.signed<EntitlementsResponse>('GET', '/api/me/entitlements');\n }\n\n async billingPortal(returnUrl: string): Promise<BillingPortalResponse> {\n const path = `/api/billing/portal?return_url=${encodeURIComponent(returnUrl)}`;\n return this.signed<BillingPortalResponse>('GET', path);\n }\n\n async trackUsage(payload: UsagePayload): Promise<UsageResponse> {\n return this.signed<UsageResponse>('POST', '/api/me/usage', payload);\n }\n\n async trackAnonymousUsage(payload: UsagePayload): Promise<UsageResponse> {\n return this.signed<UsageResponse>('POST', '/api/v1/usage/anonymous', payload);\n }\n\n async publicLicenseKeys(): Promise<LicensePublicKeysResponse> {\n return this.unsigned<LicensePublicKeysResponse>('GET', '/api/v1/license-keys/public');\n }\n\n private async signed<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const bodyBytes = body === undefined ? new Uint8Array() : new TextEncoder().encode(JSON.stringify(body));\n const timestamp = Math.floor(Date.now() / 1000);\n const nonce = newNonce();\n const canonicalString = await canonical(this.productSlug, timestamp, nonce, method, path, bodyBytes);\n const signature = await sign(this.productSecret, canonicalString);\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n [HEADER_PRODUCT]: this.productSlug,\n [HEADER_TIMESTAMP]: String(timestamp),\n [HEADER_NONCE]: nonce,\n [HEADER_SIGNATURE]: signature,\n };\n if (bodyBytes.length > 0) headers['Content-Type'] = 'application/json';\n if (this.customerToken) headers.Authorization = `Bearer ${this.customerToken}`;\n\n const res = await this.fetcher(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: bodyBytes.length > 0 ? bodyBytes : undefined,\n });\n\n return this.parseResponse<T>(res);\n }\n\n private async unsigned<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const headers: Record<string, string> = { Accept: 'application/json' };\n let bodyInit: BodyInit | undefined;\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json';\n bodyInit = JSON.stringify(body);\n }\n\n const res = await this.fetcher(`${this.baseUrl}${path}`, { method, headers, body: bodyInit });\n return this.parseResponse<T>(res);\n }\n\n private async parseResponse<T>(res: Response): Promise<T> {\n if (!res.ok) {\n let code: string;\n try {\n const parsed = (await res.json()) as { error?: string };\n code = parsed?.error ?? '';\n } catch {\n try {\n code = await res.text();\n } catch {\n code = '';\n }\n }\n throw new BillingApiError(res.status, code);\n }\n\n if (res.status === 204) {\n return undefined as T;\n }\n\n return (await res.json()) as T;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/signature.ts","../src/client.ts"],"names":[],"mappings":"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","file":"client.js","sourcesContent":["export const HEADER_PRODUCT = 'X-Akira-Product';\nexport const HEADER_TIMESTAMP = 'X-Akira-Timestamp';\nexport const HEADER_NONCE = 'X-Akira-Nonce';\nexport const HEADER_SIGNATURE = 'X-Akira-Signature';\n\nasync function sha256Hex(bytes: Uint8Array): Promise<string> {\n const digest = await getSubtle().digest('SHA-256', bytes as BufferSource);\n return bufferToHex(new Uint8Array(digest));\n}\n\nfunction getSubtle(): SubtleCrypto {\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) {\n throw new Error('Web Crypto SubtleCrypto API is not available in this runtime.');\n }\n return subtle;\n}\n\nfunction bufferToHex(buffer: Uint8Array): string {\n let out = '';\n for (const byte of buffer) {\n out += byte.toString(16).padStart(2, '0');\n }\n return out;\n}\n\nexport function newNonce(): string {\n const buf = new Uint8Array(16);\n if (globalThis.crypto?.getRandomValues) {\n globalThis.crypto.getRandomValues(buf);\n } else {\n for (let i = 0; i < buf.length; i += 1) {\n buf[i] = Math.floor(Math.random() * 256);\n }\n }\n return bufferToHex(buf);\n}\n\nexport async function canonical(\n productSlug: string,\n timestamp: number,\n nonce: string,\n method: string,\n path: string,\n body: Uint8Array,\n): Promise<string> {\n const bodyHash = await sha256Hex(body);\n return `${productSlug}\\n${timestamp}\\n${nonce}\\n${method.toUpperCase()}\\n${path}\\n${bodyHash}`;\n}\n\nexport async function sign(productSecret: string, canonicalString: string): Promise<string> {\n const subtle = getSubtle();\n const keyData = new TextEncoder().encode(productSecret) as BufferSource;\n const key = await subtle.importKey(\n 'raw',\n keyData,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n const sig = await subtle.sign('HMAC', key, new TextEncoder().encode(canonicalString) as BufferSource);\n return bufferToHex(new Uint8Array(sig));\n}\n","import {\n HEADER_NONCE,\n HEADER_PRODUCT,\n HEADER_SIGNATURE,\n HEADER_TIMESTAMP,\n canonical,\n newNonce,\n sign,\n} from './signature';\nimport type {\n BillingPortalResponse,\n Customer,\n EntitlementsResponse,\n LicenseActivatePayload,\n LicenseActivateResponse,\n LicenseCheckPayload,\n LicenseCheckResponse,\n LicensePublicKeysResponse,\n LicenseRefreshPayload,\n LicenseSyncUsagePayload,\n LicenseSyncUsageResponse,\n GithubAppInfo,\n GithubInstallationTokenPayload,\n GithubInstallationTokenResponse,\n GithubUserInstallationsResponse,\n OauthExchangePayload,\n OauthExchangeResponse,\n OauthProvidersResponse,\n OtpRequestPayload,\n OtpVerifyPayload,\n OtpVerifyResponse,\n UsagePayload,\n UsageResponse,\n} from './client-types';\n\nexport interface BillingClientConfig {\n baseUrl: string;\n productSlug: string;\n productSecret: string;\n customerToken?: string;\n fetcher?: typeof fetch;\n}\n\nexport class BillingApiError extends Error {\n status: number;\n code: string;\n constructor(status: number, code: string) {\n super(`billing api ${status}: ${code}`);\n this.status = status;\n this.code = code;\n }\n}\n\nexport class BillingClient {\n private readonly baseUrl: string;\n private readonly productSlug: string;\n private readonly productSecret: string;\n private customerToken: string | undefined;\n private readonly fetcher: typeof fetch;\n\n constructor(config: BillingClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.productSlug = config.productSlug;\n this.productSecret = config.productSecret;\n this.customerToken = config.customerToken;\n this.fetcher = config.fetcher ?? globalThis.fetch;\n if (!this.fetcher) {\n throw new Error('No fetch implementation available. Pass `fetcher` or use a runtime with global fetch.');\n }\n }\n\n setCustomerToken(token: string): void {\n this.customerToken = token;\n }\n\n async requestOtp(payload: OtpRequestPayload): Promise<void> {\n await this.signed('POST', '/api/auth/customer/otp/request', payload);\n }\n\n async verifyOtp(payload: OtpVerifyPayload): Promise<OtpVerifyResponse> {\n const res = await this.signed<OtpVerifyResponse>('POST', '/api/auth/customer/otp/verify', payload);\n this.setCustomerToken(res.access_token);\n return res;\n }\n\n async customerMe(): Promise<Customer> {\n return this.signed<Customer>('GET', '/api/me');\n }\n\n async licenseCheck(payload: LicenseCheckPayload): Promise<LicenseCheckResponse> {\n return this.signed<LicenseCheckResponse>('POST', '/api/licenses/check', payload);\n }\n\n async licenseActivate(payload: LicenseActivatePayload): Promise<LicenseActivateResponse> {\n return this.signed<LicenseActivateResponse>('POST', '/api/licenses/activate', payload);\n }\n\n async licenseRefresh(payload: LicenseRefreshPayload): Promise<LicenseActivateResponse> {\n return this.signed<LicenseActivateResponse>('POST', '/api/licenses/refresh', payload);\n }\n\n async licenseSyncUsage(payload: LicenseSyncUsagePayload): Promise<LicenseSyncUsageResponse> {\n return this.signed<LicenseSyncUsageResponse>('POST', '/api/licenses/sync-usage', payload);\n }\n\n async listOauthProviders(product: string): Promise<OauthProvidersResponse> {\n return this.signed<OauthProvidersResponse>('GET', `/api/v1/products/${encodeURIComponent(product)}/auth/providers`);\n }\n\n async exchangeOauthCode(payload: OauthExchangePayload): Promise<OauthExchangeResponse> {\n const res = await this.signed<OauthExchangeResponse>('POST', '/api/auth/oauth/exchange', payload);\n this.setCustomerToken(res.access_token);\n return res;\n }\n\n async githubInstallationToken(\n payload: GithubInstallationTokenPayload = {},\n ): Promise<GithubInstallationTokenResponse> {\n return this.signed<GithubInstallationTokenResponse>(\n 'POST',\n '/api/me/github/installation-token',\n payload,\n );\n }\n\n async meGithubInstallations(): Promise<GithubUserInstallationsResponse> {\n return this.signed<GithubUserInstallationsResponse>('GET', '/api/me/github/installations');\n }\n\n async entitlements(): Promise<EntitlementsResponse> {\n return this.signed<EntitlementsResponse>('GET', '/api/me/entitlements');\n }\n\n async billingPortal(returnUrl: string): Promise<BillingPortalResponse> {\n const path = `/api/billing/portal?return_url=${encodeURIComponent(returnUrl)}`;\n return this.signed<BillingPortalResponse>('GET', path);\n }\n\n async trackUsage(payload: UsagePayload): Promise<UsageResponse> {\n return this.signed<UsageResponse>('POST', '/api/me/usage', payload);\n }\n\n async trackAnonymousUsage(payload: UsagePayload): Promise<UsageResponse> {\n return this.signed<UsageResponse>('POST', '/api/v1/usage/anonymous', payload);\n }\n\n async publicLicenseKeys(): Promise<LicensePublicKeysResponse> {\n return this.unsigned<LicensePublicKeysResponse>('GET', '/api/v1/license-keys/public');\n }\n\n async githubAppInfo(): Promise<GithubAppInfo> {\n return this.unsigned<GithubAppInfo>('GET', '/api/v1/github/app');\n }\n\n private async signed<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const bodyBytes = body === undefined ? new Uint8Array() : new TextEncoder().encode(JSON.stringify(body));\n const timestamp = Math.floor(Date.now() / 1000);\n const nonce = newNonce();\n const canonicalString = await canonical(this.productSlug, timestamp, nonce, method, path, bodyBytes);\n const signature = await sign(this.productSecret, canonicalString);\n\n const headers: Record<string, string> = {\n Accept: 'application/json',\n [HEADER_PRODUCT]: this.productSlug,\n [HEADER_TIMESTAMP]: String(timestamp),\n [HEADER_NONCE]: nonce,\n [HEADER_SIGNATURE]: signature,\n };\n if (bodyBytes.length > 0) headers['Content-Type'] = 'application/json';\n if (this.customerToken) headers.Authorization = `Bearer ${this.customerToken}`;\n\n const res = await this.fetcher(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: bodyBytes.length > 0 ? bodyBytes : undefined,\n });\n\n return this.parseResponse<T>(res);\n }\n\n private async unsigned<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const headers: Record<string, string> = { Accept: 'application/json' };\n let bodyInit: BodyInit | undefined;\n if (body !== undefined) {\n headers['Content-Type'] = 'application/json';\n bodyInit = JSON.stringify(body);\n }\n\n const res = await this.fetcher(`${this.baseUrl}${path}`, { method, headers, body: bodyInit });\n return this.parseResponse<T>(res);\n }\n\n private async parseResponse<T>(res: Response): Promise<T> {\n if (!res.ok) {\n let code: string;\n try {\n const parsed = (await res.json()) as { error?: string };\n code = parsed?.error ?? '';\n } catch {\n try {\n code = await res.text();\n } catch {\n code = '';\n }\n }\n throw new BillingApiError(res.status, code);\n }\n\n if (res.status === 204) {\n return undefined as T;\n }\n\n return (await res.json()) as T;\n }\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -124,6 +124,9 @@ var BillingClient = class {
|
|
|
124
124
|
payload
|
|
125
125
|
);
|
|
126
126
|
}
|
|
127
|
+
async meGithubInstallations() {
|
|
128
|
+
return this.signed("GET", "/api/me/github/installations");
|
|
129
|
+
}
|
|
127
130
|
async entitlements() {
|
|
128
131
|
return this.signed("GET", "/api/me/entitlements");
|
|
129
132
|
}
|
|
@@ -140,6 +143,9 @@ var BillingClient = class {
|
|
|
140
143
|
async publicLicenseKeys() {
|
|
141
144
|
return this.unsigned("GET", "/api/v1/license-keys/public");
|
|
142
145
|
}
|
|
146
|
+
async githubAppInfo() {
|
|
147
|
+
return this.unsigned("GET", "/api/v1/github/app");
|
|
148
|
+
}
|
|
143
149
|
async signed(method, path, body) {
|
|
144
150
|
const bodyBytes = body === void 0 ? new Uint8Array() : new TextEncoder().encode(JSON.stringify(body));
|
|
145
151
|
const timestamp = Math.floor(Date.now() / 1e3);
|
|
@@ -530,17 +536,248 @@ function buildOauthInitUrl(opts) {
|
|
|
530
536
|
return `${base}/auth/${opts.provider}?${params.toString()}`;
|
|
531
537
|
}
|
|
532
538
|
|
|
539
|
+
// src/lifecycle.ts
|
|
540
|
+
function computeState(payload, graceWindowMs, now = /* @__PURE__ */ new Date()) {
|
|
541
|
+
if (!payload) return "none";
|
|
542
|
+
if (!payload.valid_until) return "invalid";
|
|
543
|
+
const expiry = Date.parse(payload.valid_until);
|
|
544
|
+
if (Number.isNaN(expiry)) return "invalid";
|
|
545
|
+
const nowMs = now.getTime();
|
|
546
|
+
if (nowMs <= expiry) {
|
|
547
|
+
return isTrialPayload(payload) ? "trialing" : "active";
|
|
548
|
+
}
|
|
549
|
+
const cutoff = expiry + graceWindowMs;
|
|
550
|
+
if (nowMs <= cutoff) return "grace";
|
|
551
|
+
return "expired";
|
|
552
|
+
}
|
|
553
|
+
function trialDaysLeft(payload, now = /* @__PURE__ */ new Date()) {
|
|
554
|
+
if (!payload || !isTrialPayload(payload)) return 0;
|
|
555
|
+
const expiry = Date.parse(payload.valid_until);
|
|
556
|
+
if (Number.isNaN(expiry)) return 0;
|
|
557
|
+
const delta = expiry - now.getTime();
|
|
558
|
+
if (delta <= 0) return 0;
|
|
559
|
+
const dayMs = 24 * 60 * 60 * 1e3;
|
|
560
|
+
return Math.ceil(delta / dayMs);
|
|
561
|
+
}
|
|
562
|
+
function isTrialPayload(payload) {
|
|
563
|
+
if (payload.features?.__trial === true) return true;
|
|
564
|
+
if (payload.plan_key && payload.plan_key.endsWith(":trial")) return true;
|
|
565
|
+
return false;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// src/gate.ts
|
|
569
|
+
var GateDeniedError = class extends Error {
|
|
570
|
+
access;
|
|
571
|
+
constructor(access) {
|
|
572
|
+
super(`billing: feature "${access.feature}" denied (${access.reason})`);
|
|
573
|
+
this.name = "GateDeniedError";
|
|
574
|
+
this.access = access;
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
function isGateDenied(err) {
|
|
578
|
+
return err instanceof GateDeniedError;
|
|
579
|
+
}
|
|
580
|
+
var Gate = class {
|
|
581
|
+
loader;
|
|
582
|
+
localConsumption;
|
|
583
|
+
graceWindowMs;
|
|
584
|
+
now;
|
|
585
|
+
inflight = null;
|
|
586
|
+
constructor(opts) {
|
|
587
|
+
if (!opts.loader) throw new Error("billing: Gate requires loader");
|
|
588
|
+
this.loader = opts.loader;
|
|
589
|
+
this.localConsumption = opts.localConsumption ?? (() => 0);
|
|
590
|
+
this.graceWindowMs = opts.graceWindowMs ?? 0;
|
|
591
|
+
this.now = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
592
|
+
}
|
|
593
|
+
async check(feature) {
|
|
594
|
+
const prev = this.inflight;
|
|
595
|
+
const run = (async () => {
|
|
596
|
+
if (prev) {
|
|
597
|
+
try {
|
|
598
|
+
await prev;
|
|
599
|
+
} catch {
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
return this.evaluate(feature);
|
|
603
|
+
})();
|
|
604
|
+
this.inflight = run.catch(() => ({}));
|
|
605
|
+
return run;
|
|
606
|
+
}
|
|
607
|
+
async require(feature) {
|
|
608
|
+
const access = await this.check(feature);
|
|
609
|
+
if (!access.allowed) throw new GateDeniedError(access);
|
|
610
|
+
return access;
|
|
611
|
+
}
|
|
612
|
+
async evaluate(feature) {
|
|
613
|
+
const access = {
|
|
614
|
+
feature,
|
|
615
|
+
allowed: false,
|
|
616
|
+
hasFeature: false,
|
|
617
|
+
unlimited: false,
|
|
618
|
+
remaining: 0,
|
|
619
|
+
reason: "",
|
|
620
|
+
plan: "",
|
|
621
|
+
state: "none"
|
|
622
|
+
};
|
|
623
|
+
let loaded;
|
|
624
|
+
try {
|
|
625
|
+
loaded = await this.loader();
|
|
626
|
+
} catch (err) {
|
|
627
|
+
access.reason = "verify_failed";
|
|
628
|
+
throw Object.assign(err instanceof Error ? err : new Error(String(err)), { access });
|
|
629
|
+
}
|
|
630
|
+
if (!loaded) {
|
|
631
|
+
access.reason = "no_license";
|
|
632
|
+
return access;
|
|
633
|
+
}
|
|
634
|
+
const { payload } = loaded;
|
|
635
|
+
access.plan = payload.plan_key;
|
|
636
|
+
access.state = computeState(payload, this.graceWindowMs, this.now());
|
|
637
|
+
if (access.state === "expired" || access.state === "invalid") {
|
|
638
|
+
access.reason = `license_${access.state}`;
|
|
639
|
+
return access;
|
|
640
|
+
}
|
|
641
|
+
const featureFlag = payload.features?.[feature];
|
|
642
|
+
if (featureFlag !== void 0) {
|
|
643
|
+
access.hasFeature = featureFlag;
|
|
644
|
+
if (!featureFlag) {
|
|
645
|
+
access.reason = "feature_disabled";
|
|
646
|
+
return access;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
let consumed;
|
|
650
|
+
try {
|
|
651
|
+
consumed = await this.localConsumption(feature);
|
|
652
|
+
} catch (err) {
|
|
653
|
+
access.reason = "local_consumption_failed";
|
|
654
|
+
throw Object.assign(err instanceof Error ? err : new Error(String(err)), { access });
|
|
655
|
+
}
|
|
656
|
+
const remaining = computeRemaining(payload, feature, consumed);
|
|
657
|
+
if (remaining === null) {
|
|
658
|
+
if (access.hasFeature) {
|
|
659
|
+
access.allowed = true;
|
|
660
|
+
access.unlimited = true;
|
|
661
|
+
return access;
|
|
662
|
+
}
|
|
663
|
+
access.reason = "feature_missing";
|
|
664
|
+
return access;
|
|
665
|
+
}
|
|
666
|
+
if (remaining === Number.POSITIVE_INFINITY) {
|
|
667
|
+
access.unlimited = true;
|
|
668
|
+
access.hasFeature = true;
|
|
669
|
+
access.allowed = true;
|
|
670
|
+
return access;
|
|
671
|
+
}
|
|
672
|
+
access.remaining = remaining;
|
|
673
|
+
if (remaining > 0) {
|
|
674
|
+
access.allowed = true;
|
|
675
|
+
access.hasFeature = true;
|
|
676
|
+
return access;
|
|
677
|
+
}
|
|
678
|
+
access.reason = "limit_reached";
|
|
679
|
+
return access;
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
// src/usage.ts
|
|
684
|
+
var MemoryBuffer = class {
|
|
685
|
+
state = {};
|
|
686
|
+
add(feature, delta) {
|
|
687
|
+
if (delta === 0) return;
|
|
688
|
+
this.state[feature] = (this.state[feature] ?? 0) + delta;
|
|
689
|
+
}
|
|
690
|
+
drain() {
|
|
691
|
+
const out = this.state;
|
|
692
|
+
this.state = {};
|
|
693
|
+
return out;
|
|
694
|
+
}
|
|
695
|
+
restore(deltas) {
|
|
696
|
+
for (const [k, v] of Object.entries(deltas)) {
|
|
697
|
+
this.state[k] = (this.state[k] ?? 0) + v;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
var DEFAULT_FLUSH_INTERVAL_MS = 5 * 60 * 1e3;
|
|
702
|
+
var UsageTracker = class {
|
|
703
|
+
buffer;
|
|
704
|
+
sync;
|
|
705
|
+
serial;
|
|
706
|
+
onRefresh;
|
|
707
|
+
flushIntervalMs;
|
|
708
|
+
timer = null;
|
|
709
|
+
running = false;
|
|
710
|
+
constructor(opts) {
|
|
711
|
+
if (!opts.buffer) throw new Error("billing: tracker requires buffer");
|
|
712
|
+
if (!opts.sync) throw new Error("billing: tracker requires sync");
|
|
713
|
+
this.buffer = opts.buffer;
|
|
714
|
+
this.sync = opts.sync;
|
|
715
|
+
if (opts.serial !== void 0) this.serial = opts.serial;
|
|
716
|
+
if (opts.onRefresh !== void 0) this.onRefresh = opts.onRefresh;
|
|
717
|
+
this.flushIntervalMs = opts.flushIntervalMs && opts.flushIntervalMs > 0 ? opts.flushIntervalMs : DEFAULT_FLUSH_INTERVAL_MS;
|
|
718
|
+
}
|
|
719
|
+
async track(feature, delta) {
|
|
720
|
+
if (delta === 0) return;
|
|
721
|
+
await this.buffer.add(feature, delta);
|
|
722
|
+
}
|
|
723
|
+
async flush() {
|
|
724
|
+
const deltas = await this.buffer.drain();
|
|
725
|
+
if (!deltas || Object.keys(deltas).length === 0) return;
|
|
726
|
+
let serial = 0;
|
|
727
|
+
if (this.serial) {
|
|
728
|
+
try {
|
|
729
|
+
serial = await this.serial();
|
|
730
|
+
} catch (err) {
|
|
731
|
+
await this.buffer.restore(deltas);
|
|
732
|
+
throw err;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
let resp;
|
|
736
|
+
try {
|
|
737
|
+
resp = await this.sync(deltas, serial);
|
|
738
|
+
} catch (err) {
|
|
739
|
+
await this.buffer.restore(deltas);
|
|
740
|
+
throw err;
|
|
741
|
+
}
|
|
742
|
+
if (this.onRefresh && resp) {
|
|
743
|
+
await this.onRefresh(resp);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
start() {
|
|
747
|
+
if (this.running) return;
|
|
748
|
+
this.running = true;
|
|
749
|
+
this.timer = setInterval(() => {
|
|
750
|
+
void this.flush().catch(() => {
|
|
751
|
+
});
|
|
752
|
+
}, this.flushIntervalMs);
|
|
753
|
+
}
|
|
754
|
+
async stop() {
|
|
755
|
+
if (!this.running) return;
|
|
756
|
+
this.running = false;
|
|
757
|
+
if (this.timer) {
|
|
758
|
+
clearInterval(this.timer);
|
|
759
|
+
this.timer = null;
|
|
760
|
+
}
|
|
761
|
+
await this.flush();
|
|
762
|
+
}
|
|
763
|
+
};
|
|
764
|
+
|
|
533
765
|
exports.BillingApiError = BillingApiError;
|
|
534
766
|
exports.BillingClient = BillingClient;
|
|
767
|
+
exports.Gate = Gate;
|
|
768
|
+
exports.GateDeniedError = GateDeniedError;
|
|
535
769
|
exports.HEADER_NONCE = HEADER_NONCE;
|
|
536
770
|
exports.HEADER_PRODUCT = HEADER_PRODUCT;
|
|
537
771
|
exports.HEADER_SIGNATURE = HEADER_SIGNATURE;
|
|
538
772
|
exports.HEADER_TIMESTAMP = HEADER_TIMESTAMP;
|
|
773
|
+
exports.MemoryBuffer = MemoryBuffer;
|
|
774
|
+
exports.UsageTracker = UsageTracker;
|
|
539
775
|
exports.buildOauthInitUrl = buildOauthInitUrl;
|
|
540
776
|
exports.canUseUpdate = canUseUpdate;
|
|
541
777
|
exports.canonical = canonical;
|
|
542
778
|
exports.checkoutUrl = checkoutUrl;
|
|
543
779
|
exports.computeRemaining = computeRemaining;
|
|
780
|
+
exports.computeState = computeState;
|
|
544
781
|
exports.decodeLicense = decodeLicense;
|
|
545
782
|
exports.defaultInterval = defaultInterval;
|
|
546
783
|
exports.downloadUrl = downloadUrl;
|
|
@@ -553,6 +790,7 @@ exports.getCtaProps = getCtaProps;
|
|
|
553
790
|
exports.hasYearly = hasYearly;
|
|
554
791
|
exports.isExpired = isExpired;
|
|
555
792
|
exports.isFreeTier = isFreeTier;
|
|
793
|
+
exports.isGateDenied = isGateDenied;
|
|
556
794
|
exports.isInGrace = isInGrace;
|
|
557
795
|
exports.isOneTimeTier = isOneTimeTier;
|
|
558
796
|
exports.isUnlimited = isUnlimited;
|
|
@@ -561,6 +799,7 @@ exports.newNonce = newNonce;
|
|
|
561
799
|
exports.periodResetAt = periodResetAt;
|
|
562
800
|
exports.sendCompletionBeacon = sendCompletionBeacon;
|
|
563
801
|
exports.sign = sign;
|
|
802
|
+
exports.trialDaysLeft = trialDaysLeft;
|
|
564
803
|
exports.triggerDownload = triggerDownload;
|
|
565
804
|
exports.verifyLicense = verifyLicense;
|
|
566
805
|
//# sourceMappingURL=index.cjs.map
|