@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.
@@ -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, GithubInstallationTokenPayload as G, LicenseActivatePayload as L, OauthExchangeEntitlement as O, PkceChallenge as P, SignedLicense as S, UsageFeatureState as U, BuildOauthInitUrlOptions as a, EntitlementsResponse as b, GithubInstallationTokenResponse as c, LicenseActivateResponse as d, LicenseCheckPayload as e, LicenseCheckResponse as f, LicensePublicKey as g, LicensePublicKeysResponse as h, LicenseRefreshPayload as i, LicenseSnapshotPayload as j, LicenseSyncUsagePayload as k, LicenseSyncUsageResponse as l, LicensingMode as m, OauthExchangePayload as n, OauthExchangeResponse as o, OauthProvider as p, OauthProviderInfo as q, OauthProvidersResponse as r, OtpCustomer as s, OtpRequestPayload as t, OtpVerifyPayload as u, OtpVerifyResponse as v, UsagePayload as w, UsageResponse as x };
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, GithubInstallationTokenPayload as G, LicenseActivatePayload as L, OauthExchangeEntitlement as O, PkceChallenge as P, SignedLicense as S, UsageFeatureState as U, BuildOauthInitUrlOptions as a, EntitlementsResponse as b, GithubInstallationTokenResponse as c, LicenseActivateResponse as d, LicenseCheckPayload as e, LicenseCheckResponse as f, LicensePublicKey as g, LicensePublicKeysResponse as h, LicenseRefreshPayload as i, LicenseSnapshotPayload as j, LicenseSyncUsagePayload as k, LicenseSyncUsageResponse as l, LicensingMode as m, OauthExchangePayload as n, OauthExchangeResponse as o, OauthProvider as p, OauthProviderInfo as q, OauthProvidersResponse as r, OtpCustomer as s, OtpRequestPayload as t, OtpVerifyPayload as u, OtpVerifyResponse as v, UsagePayload as w, UsageResponse as x };
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);
@@ -1 +1 @@
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 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 { t as OtpRequestPayload, u as OtpVerifyPayload, v as OtpVerifyResponse, C as Customer, e as LicenseCheckPayload, f as LicenseCheckResponse, L as LicenseActivatePayload, d as LicenseActivateResponse, i as LicenseRefreshPayload, k as LicenseSyncUsagePayload, l as LicenseSyncUsageResponse, r as OauthProvidersResponse, n as OauthExchangePayload, o as OauthExchangeResponse, G as GithubInstallationTokenPayload, c as GithubInstallationTokenResponse, b as EntitlementsResponse, B as BillingPortalResponse, w as UsagePayload, x as UsageResponse, h as LicensePublicKeysResponse } from './client-types-B3lf4xBs.cjs';
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 { t as OtpRequestPayload, u as OtpVerifyPayload, v as OtpVerifyResponse, C as Customer, e as LicenseCheckPayload, f as LicenseCheckResponse, L as LicenseActivatePayload, d as LicenseActivateResponse, i as LicenseRefreshPayload, k as LicenseSyncUsagePayload, l as LicenseSyncUsageResponse, r as OauthProvidersResponse, n as OauthExchangePayload, o as OauthExchangeResponse, G as GithubInstallationTokenPayload, c as GithubInstallationTokenResponse, b as EntitlementsResponse, B as BillingPortalResponse, w as UsagePayload, x as UsageResponse, h as LicensePublicKeysResponse } from './client-types-B3lf4xBs.js';
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);
@@ -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