@akira-io/billing-js 0.1.5 → 0.1.7

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/license.ts"],"names":[],"mappings":"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","file":"license.cjs","sourcesContent":["import type {\n LicenseSnapshotPayload,\n SignedLicense,\n UsageFeatureState,\n} from './client-types';\n\nexport interface DecodedLicense {\n raw: SignedLicense;\n payload: LicenseSnapshotPayload;\n}\n\nfunction base64Decode(input: string): Uint8Array<ArrayBuffer> {\n const bin = atob(input);\n const buf = new ArrayBuffer(bin.length);\n const out = new Uint8Array(buf);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nexport function decodeLicense(signed: SignedLicense): DecodedLicense {\n const payloadJson = new TextDecoder().decode(base64Decode(signed.payload));\n const payload = JSON.parse(payloadJson) as LicenseSnapshotPayload;\n return { raw: signed, payload };\n}\n\nexport async function verifyLicense(signed: SignedLicense, publicKeyBase64: string): Promise<boolean> {\n if (signed.algorithm !== 'ed25519') return false;\n\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) throw new Error('crypto.subtle not available; cannot verify license');\n\n const payloadBytes = base64Decode(signed.payload);\n const signatureBytes = base64Decode(signed.signature);\n const publicKeyBytes = base64Decode(publicKeyBase64);\n\n const key = await subtle.importKey(\n 'raw',\n publicKeyBytes,\n { name: 'Ed25519' } as AlgorithmIdentifier,\n false,\n ['verify'],\n );\n\n return subtle.verify({ name: 'Ed25519' } as AlgorithmIdentifier, key, signatureBytes, payloadBytes);\n}\n\nexport function computeRemaining(\n payload: LicenseSnapshotPayload,\n feature: string,\n consumedLocal = 0,\n): number | null {\n const state = payload.usage?.[feature];\n if (!state) return null;\n if (state.type === 'bool') return state.enabled ? Number.POSITIVE_INFINITY : 0;\n return Math.max(0, state.allowance - state.consumed_at_issue - consumedLocal);\n}\n\nexport function isUnlimited(state: UsageFeatureState | undefined): boolean {\n if (!state) return false;\n if (state.type === 'bool') return state.enabled;\n return state.allowance === 0;\n}\n\nexport function isExpired(payload: LicenseSnapshotPayload, now: Date = new Date()): boolean {\n return new Date(payload.valid_until).getTime() < now.getTime();\n}\n\nexport function isInGrace(\n payload: LicenseSnapshotPayload,\n graceSeconds: number,\n now: Date = new Date(),\n): boolean {\n const expiry = new Date(payload.valid_until).getTime();\n return now.getTime() <= expiry + graceSeconds * 1000;\n}\n\nexport function canUseUpdate(payload: LicenseSnapshotPayload, releaseDate: string | Date): boolean {\n if (!payload.paid_up_until) return true;\n const release = releaseDate instanceof Date ? releaseDate : new Date(releaseDate);\n const paidUp = new Date(payload.paid_up_until);\n return release.getTime() <= paidUp.getTime();\n}\n\nexport function periodResetAt(payload: LicenseSnapshotPayload, feature: string): Date | null {\n const state = payload.usage?.[feature];\n if (!state || state.type !== 'counter') return null;\n return new Date(state.period_end);\n}\n"]}
1
+ {"version":3,"sources":["../src/license.ts"],"names":[],"mappings":"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","file":"license.cjs","sourcesContent":["import type {\n LicenseSnapshotPayload,\n SignedLicense,\n UsageFeatureState,\n} from './client-types';\n\nexport interface DecodedLicense {\n raw: SignedLicense;\n payload: LicenseSnapshotPayload;\n}\n\nfunction base64Decode(input: string): Uint8Array<ArrayBuffer> {\n const bin = atob(input);\n const buf = new ArrayBuffer(bin.length);\n const out = new Uint8Array(buf);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nexport function decodeLicense(signed: SignedLicense): DecodedLicense {\n const payloadJson = new TextDecoder().decode(base64Decode(signed.payload));\n const payload = JSON.parse(payloadJson) as LicenseSnapshotPayload;\n return { raw: signed, payload };\n}\n\nexport async function verifyLicense(signed: SignedLicense, publicKeyBase64: string): Promise<boolean> {\n if (signed.algorithm !== 'ed25519') return false;\n\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) throw new Error('crypto.subtle not available; cannot verify license');\n\n const payloadBytes = base64Decode(signed.payload);\n const signatureBytes = base64Decode(signed.signature);\n const publicKeyBytes = base64Decode(publicKeyBase64);\n\n const key = await subtle.importKey(\n 'raw',\n publicKeyBytes,\n { name: 'Ed25519' } as AlgorithmIdentifier,\n false,\n ['verify'],\n );\n\n return subtle.verify({ name: 'Ed25519' } as AlgorithmIdentifier, key, signatureBytes, payloadBytes);\n}\n\nexport function computeRemaining(\n payload: LicenseSnapshotPayload,\n feature: string,\n consumedLocal = 0,\n): number | null {\n const state = payload.usage?.[feature];\n if (!state) return null;\n if (state.type === 'bool') return state.enabled ? Number.POSITIVE_INFINITY : 0;\n return Math.max(0, state.allowance - state.consumed_at_issue - consumedLocal);\n}\n\nexport function isUnlimited(state: UsageFeatureState | undefined): boolean {\n if (!state) return false;\n if (state.type === 'bool') return state.enabled;\n return state.allowance === 0;\n}\n\nexport function isExpired(payload: LicenseSnapshotPayload, now: Date = new Date()): boolean {\n return new Date(payload.valid_until).getTime() < now.getTime();\n}\n\nexport function isInGrace(\n payload: LicenseSnapshotPayload,\n graceSeconds: number,\n now: Date = new Date(),\n): boolean {\n const expiry = new Date(payload.valid_until).getTime();\n return now.getTime() <= expiry + graceSeconds * 1000;\n}\n\nexport function canUseUpdate(payload: LicenseSnapshotPayload, releaseDate: string | Date): boolean {\n const release = releaseDate instanceof Date ? releaseDate : new Date(releaseDate);\n\n const paidUpMs = payload.paid_up_until ? new Date(payload.paid_up_until).getTime() : null;\n const fallbackMs = payload.fallback_release_date\n ? new Date(payload.fallback_release_date).getTime()\n : null;\n\n if (paidUpMs === null && fallbackMs === null) return true;\n\n const effective = Math.max(paidUpMs ?? -Infinity, fallbackMs ?? -Infinity);\n const windowMs = (payload.updates_window_days ?? 0) * 86_400_000;\n return release.getTime() <= effective + windowMs;\n}\n\nexport function periodResetAt(payload: LicenseSnapshotPayload, feature: string): Date | null {\n const state = payload.usage?.[feature];\n if (!state || state.type !== 'counter') return null;\n return new Date(state.period_end);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { S as SignedLicense, h as LicenseSnapshotPayload, U as UsageFeatureState } from './client-types-CN3dVIrX.cjs';
1
+ import { S as SignedLicense, i as LicenseSnapshotPayload, U as UsageFeatureState } from './client-types-CIqyeWNV.cjs';
2
2
 
3
3
  interface DecodedLicense {
4
4
  raw: SignedLicense;
package/dist/license.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { S as SignedLicense, h as LicenseSnapshotPayload, U as UsageFeatureState } from './client-types-CN3dVIrX.js';
1
+ import { S as SignedLicense, i as LicenseSnapshotPayload, U as UsageFeatureState } from './client-types-CIqyeWNV.js';
2
2
 
3
3
  interface DecodedLicense {
4
4
  raw: SignedLicense;
package/dist/license.js CHANGED
@@ -46,10 +46,13 @@ function isInGrace(payload, graceSeconds, now = /* @__PURE__ */ new Date()) {
46
46
  return now.getTime() <= expiry + graceSeconds * 1e3;
47
47
  }
48
48
  function canUseUpdate(payload, releaseDate) {
49
- if (!payload.paid_up_until) return true;
50
49
  const release = releaseDate instanceof Date ? releaseDate : new Date(releaseDate);
51
- const paidUp = new Date(payload.paid_up_until);
52
- return release.getTime() <= paidUp.getTime();
50
+ const paidUpMs = payload.paid_up_until ? new Date(payload.paid_up_until).getTime() : null;
51
+ const fallbackMs = payload.fallback_release_date ? new Date(payload.fallback_release_date).getTime() : null;
52
+ if (paidUpMs === null && fallbackMs === null) return true;
53
+ const effective = Math.max(paidUpMs ?? -Infinity, fallbackMs ?? -Infinity);
54
+ const windowMs = (payload.updates_window_days ?? 0) * 864e5;
55
+ return release.getTime() <= effective + windowMs;
53
56
  }
54
57
  function periodResetAt(payload, feature) {
55
58
  const state = payload.usage?.[feature];
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/license.ts"],"names":[],"mappings":"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","file":"license.js","sourcesContent":["import type {\n LicenseSnapshotPayload,\n SignedLicense,\n UsageFeatureState,\n} from './client-types';\n\nexport interface DecodedLicense {\n raw: SignedLicense;\n payload: LicenseSnapshotPayload;\n}\n\nfunction base64Decode(input: string): Uint8Array<ArrayBuffer> {\n const bin = atob(input);\n const buf = new ArrayBuffer(bin.length);\n const out = new Uint8Array(buf);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nexport function decodeLicense(signed: SignedLicense): DecodedLicense {\n const payloadJson = new TextDecoder().decode(base64Decode(signed.payload));\n const payload = JSON.parse(payloadJson) as LicenseSnapshotPayload;\n return { raw: signed, payload };\n}\n\nexport async function verifyLicense(signed: SignedLicense, publicKeyBase64: string): Promise<boolean> {\n if (signed.algorithm !== 'ed25519') return false;\n\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) throw new Error('crypto.subtle not available; cannot verify license');\n\n const payloadBytes = base64Decode(signed.payload);\n const signatureBytes = base64Decode(signed.signature);\n const publicKeyBytes = base64Decode(publicKeyBase64);\n\n const key = await subtle.importKey(\n 'raw',\n publicKeyBytes,\n { name: 'Ed25519' } as AlgorithmIdentifier,\n false,\n ['verify'],\n );\n\n return subtle.verify({ name: 'Ed25519' } as AlgorithmIdentifier, key, signatureBytes, payloadBytes);\n}\n\nexport function computeRemaining(\n payload: LicenseSnapshotPayload,\n feature: string,\n consumedLocal = 0,\n): number | null {\n const state = payload.usage?.[feature];\n if (!state) return null;\n if (state.type === 'bool') return state.enabled ? Number.POSITIVE_INFINITY : 0;\n return Math.max(0, state.allowance - state.consumed_at_issue - consumedLocal);\n}\n\nexport function isUnlimited(state: UsageFeatureState | undefined): boolean {\n if (!state) return false;\n if (state.type === 'bool') return state.enabled;\n return state.allowance === 0;\n}\n\nexport function isExpired(payload: LicenseSnapshotPayload, now: Date = new Date()): boolean {\n return new Date(payload.valid_until).getTime() < now.getTime();\n}\n\nexport function isInGrace(\n payload: LicenseSnapshotPayload,\n graceSeconds: number,\n now: Date = new Date(),\n): boolean {\n const expiry = new Date(payload.valid_until).getTime();\n return now.getTime() <= expiry + graceSeconds * 1000;\n}\n\nexport function canUseUpdate(payload: LicenseSnapshotPayload, releaseDate: string | Date): boolean {\n if (!payload.paid_up_until) return true;\n const release = releaseDate instanceof Date ? releaseDate : new Date(releaseDate);\n const paidUp = new Date(payload.paid_up_until);\n return release.getTime() <= paidUp.getTime();\n}\n\nexport function periodResetAt(payload: LicenseSnapshotPayload, feature: string): Date | null {\n const state = payload.usage?.[feature];\n if (!state || state.type !== 'counter') return null;\n return new Date(state.period_end);\n}\n"]}
1
+ {"version":3,"sources":["../src/license.ts"],"names":[],"mappings":"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","file":"license.js","sourcesContent":["import type {\n LicenseSnapshotPayload,\n SignedLicense,\n UsageFeatureState,\n} from './client-types';\n\nexport interface DecodedLicense {\n raw: SignedLicense;\n payload: LicenseSnapshotPayload;\n}\n\nfunction base64Decode(input: string): Uint8Array<ArrayBuffer> {\n const bin = atob(input);\n const buf = new ArrayBuffer(bin.length);\n const out = new Uint8Array(buf);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nexport function decodeLicense(signed: SignedLicense): DecodedLicense {\n const payloadJson = new TextDecoder().decode(base64Decode(signed.payload));\n const payload = JSON.parse(payloadJson) as LicenseSnapshotPayload;\n return { raw: signed, payload };\n}\n\nexport async function verifyLicense(signed: SignedLicense, publicKeyBase64: string): Promise<boolean> {\n if (signed.algorithm !== 'ed25519') return false;\n\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) throw new Error('crypto.subtle not available; cannot verify license');\n\n const payloadBytes = base64Decode(signed.payload);\n const signatureBytes = base64Decode(signed.signature);\n const publicKeyBytes = base64Decode(publicKeyBase64);\n\n const key = await subtle.importKey(\n 'raw',\n publicKeyBytes,\n { name: 'Ed25519' } as AlgorithmIdentifier,\n false,\n ['verify'],\n );\n\n return subtle.verify({ name: 'Ed25519' } as AlgorithmIdentifier, key, signatureBytes, payloadBytes);\n}\n\nexport function computeRemaining(\n payload: LicenseSnapshotPayload,\n feature: string,\n consumedLocal = 0,\n): number | null {\n const state = payload.usage?.[feature];\n if (!state) return null;\n if (state.type === 'bool') return state.enabled ? Number.POSITIVE_INFINITY : 0;\n return Math.max(0, state.allowance - state.consumed_at_issue - consumedLocal);\n}\n\nexport function isUnlimited(state: UsageFeatureState | undefined): boolean {\n if (!state) return false;\n if (state.type === 'bool') return state.enabled;\n return state.allowance === 0;\n}\n\nexport function isExpired(payload: LicenseSnapshotPayload, now: Date = new Date()): boolean {\n return new Date(payload.valid_until).getTime() < now.getTime();\n}\n\nexport function isInGrace(\n payload: LicenseSnapshotPayload,\n graceSeconds: number,\n now: Date = new Date(),\n): boolean {\n const expiry = new Date(payload.valid_until).getTime();\n return now.getTime() <= expiry + graceSeconds * 1000;\n}\n\nexport function canUseUpdate(payload: LicenseSnapshotPayload, releaseDate: string | Date): boolean {\n const release = releaseDate instanceof Date ? releaseDate : new Date(releaseDate);\n\n const paidUpMs = payload.paid_up_until ? new Date(payload.paid_up_until).getTime() : null;\n const fallbackMs = payload.fallback_release_date\n ? new Date(payload.fallback_release_date).getTime()\n : null;\n\n if (paidUpMs === null && fallbackMs === null) return true;\n\n const effective = Math.max(paidUpMs ?? -Infinity, fallbackMs ?? -Infinity);\n const windowMs = (payload.updates_window_days ?? 0) * 86_400_000;\n return release.getTime() <= effective + windowMs;\n}\n\nexport function periodResetAt(payload: LicenseSnapshotPayload, feature: string): Date | null {\n const state = payload.usage?.[feature];\n if (!state || state.type !== 'counter') return null;\n return new Date(state.period_end);\n}\n"]}
package/dist/oauth.cjs ADDED
@@ -0,0 +1,41 @@
1
+ 'use strict';
2
+
3
+ // src/oauth.ts
4
+ function bytesToUrlSafeBase64(bytes) {
5
+ let bin = "";
6
+ for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
7
+ return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
8
+ }
9
+ function randomBytes(length) {
10
+ const buf = new Uint8Array(length);
11
+ globalThis.crypto.getRandomValues(buf);
12
+ return buf;
13
+ }
14
+ async function generatePkceChallenge() {
15
+ const subtle = globalThis.crypto?.subtle;
16
+ if (!subtle) throw new Error("crypto.subtle not available; cannot generate PKCE challenge");
17
+ const verifier = bytesToUrlSafeBase64(randomBytes(48));
18
+ const hash = await subtle.digest("SHA-256", new TextEncoder().encode(verifier));
19
+ const challenge = bytesToUrlSafeBase64(new Uint8Array(hash));
20
+ return { verifier, challenge, method: "S256" };
21
+ }
22
+ function generateOauthState() {
23
+ return bytesToUrlSafeBase64(randomBytes(24));
24
+ }
25
+ function buildOauthInitUrl(opts) {
26
+ const base = opts.baseUrl.replace(/\/$/, "");
27
+ const params = new URLSearchParams({
28
+ product: opts.product,
29
+ redirect_uri: opts.redirectUri,
30
+ code_challenge: opts.codeChallenge,
31
+ code_challenge_method: opts.codeChallengeMethod ?? "S256"
32
+ });
33
+ if (opts.state) params.set("state", opts.state);
34
+ return `${base}/auth/${opts.provider}?${params.toString()}`;
35
+ }
36
+
37
+ exports.buildOauthInitUrl = buildOauthInitUrl;
38
+ exports.generateOauthState = generateOauthState;
39
+ exports.generatePkceChallenge = generatePkceChallenge;
40
+ //# sourceMappingURL=oauth.cjs.map
41
+ //# sourceMappingURL=oauth.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/oauth.ts"],"names":[],"mappings":";;;AAEA,SAAS,qBAAqB,KAAA,EAA2B;AACrD,EAAA,IAAI,GAAA,GAAM,EAAA;AACV,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,MAAA,EAAQ,CAAA,EAAA,EAAK,GAAA,IAAO,MAAA,CAAO,YAAA,CAAa,KAAA,CAAM,CAAC,CAAW,CAAA;AACpF,EAAA,OAAO,IAAA,CAAK,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC9E;AAEA,SAAS,YAAY,MAAA,EAA4B;AAC7C,EAAA,MAAM,GAAA,GAAM,IAAI,UAAA,CAAW,MAAM,CAAA;AACjC,EAAA,UAAA,CAAW,MAAA,CAAO,gBAAgB,GAAG,CAAA;AACrC,EAAA,OAAO,GAAA;AACX;AAEA,eAAsB,qBAAA,GAAgD;AAClE,EAAA,MAAM,MAAA,GAAS,WAAW,MAAA,EAAQ,MAAA;AAClC,EAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,MAAM,6DAA6D,CAAA;AAE1F,EAAA,MAAM,QAAA,GAAW,oBAAA,CAAqB,WAAA,CAAY,EAAE,CAAC,CAAA;AACrD,EAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,QAAQ,CAAC,CAAA;AAC9E,EAAA,MAAM,SAAA,GAAY,oBAAA,CAAqB,IAAI,UAAA,CAAW,IAAI,CAAC,CAAA;AAE3D,EAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,MAAA,EAAQ,MAAA,EAAO;AACjD;AAEO,SAAS,kBAAA,GAA6B;AACzC,EAAA,OAAO,oBAAA,CAAqB,WAAA,CAAY,EAAE,CAAC,CAAA;AAC/C;AAEO,SAAS,kBAAkB,IAAA,EAAwC;AACtE,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC3C,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,CAAgB;AAAA,IAC/B,SAAS,IAAA,CAAK,OAAA;AAAA,IACd,cAAc,IAAA,CAAK,WAAA;AAAA,IACnB,gBAAgB,IAAA,CAAK,aAAA;AAAA,IACrB,qBAAA,EAAuB,KAAK,mBAAA,IAAuB;AAAA,GACtD,CAAA;AACD,EAAA,IAAI,KAAK,KAAA,EAAO,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,KAAK,KAAK,CAAA;AAE9C,EAAA,OAAO,CAAA,EAAG,IAAI,CAAA,MAAA,EAAS,IAAA,CAAK,QAAQ,CAAA,CAAA,EAAI,MAAA,CAAO,UAAU,CAAA,CAAA;AAC7D","file":"oauth.cjs","sourcesContent":["import type { BuildOauthInitUrlOptions, PkceChallenge } from './client-types';\n\nfunction bytesToUrlSafeBase64(bytes: Uint8Array): string {\n let bin = '';\n for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i] as number);\n return btoa(bin).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction randomBytes(length: number): Uint8Array {\n const buf = new Uint8Array(length);\n globalThis.crypto.getRandomValues(buf);\n return buf;\n}\n\nexport async function generatePkceChallenge(): Promise<PkceChallenge> {\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) throw new Error('crypto.subtle not available; cannot generate PKCE challenge');\n\n const verifier = bytesToUrlSafeBase64(randomBytes(48));\n const hash = await subtle.digest('SHA-256', new TextEncoder().encode(verifier));\n const challenge = bytesToUrlSafeBase64(new Uint8Array(hash));\n\n return { verifier, challenge, method: 'S256' };\n}\n\nexport function generateOauthState(): string {\n return bytesToUrlSafeBase64(randomBytes(24));\n}\n\nexport function buildOauthInitUrl(opts: BuildOauthInitUrlOptions): string {\n const base = opts.baseUrl.replace(/\\/$/, '');\n const params = new URLSearchParams({\n product: opts.product,\n redirect_uri: opts.redirectUri,\n code_challenge: opts.codeChallenge,\n code_challenge_method: opts.codeChallengeMethod ?? 'S256',\n });\n if (opts.state) params.set('state', opts.state);\n\n return `${base}/auth/${opts.provider}?${params.toString()}`;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import { a as BuildOauthInitUrlOptions, P as PkceChallenge } from './client-types-CIqyeWNV.cjs';
2
+
3
+ declare function generatePkceChallenge(): Promise<PkceChallenge>;
4
+ declare function generateOauthState(): string;
5
+ declare function buildOauthInitUrl(opts: BuildOauthInitUrlOptions): string;
6
+
7
+ export { buildOauthInitUrl, generateOauthState, generatePkceChallenge };
@@ -0,0 +1,7 @@
1
+ import { a as BuildOauthInitUrlOptions, P as PkceChallenge } from './client-types-CIqyeWNV.js';
2
+
3
+ declare function generatePkceChallenge(): Promise<PkceChallenge>;
4
+ declare function generateOauthState(): string;
5
+ declare function buildOauthInitUrl(opts: BuildOauthInitUrlOptions): string;
6
+
7
+ export { buildOauthInitUrl, generateOauthState, generatePkceChallenge };
package/dist/oauth.js ADDED
@@ -0,0 +1,37 @@
1
+ // src/oauth.ts
2
+ function bytesToUrlSafeBase64(bytes) {
3
+ let bin = "";
4
+ for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
5
+ return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
6
+ }
7
+ function randomBytes(length) {
8
+ const buf = new Uint8Array(length);
9
+ globalThis.crypto.getRandomValues(buf);
10
+ return buf;
11
+ }
12
+ async function generatePkceChallenge() {
13
+ const subtle = globalThis.crypto?.subtle;
14
+ if (!subtle) throw new Error("crypto.subtle not available; cannot generate PKCE challenge");
15
+ const verifier = bytesToUrlSafeBase64(randomBytes(48));
16
+ const hash = await subtle.digest("SHA-256", new TextEncoder().encode(verifier));
17
+ const challenge = bytesToUrlSafeBase64(new Uint8Array(hash));
18
+ return { verifier, challenge, method: "S256" };
19
+ }
20
+ function generateOauthState() {
21
+ return bytesToUrlSafeBase64(randomBytes(24));
22
+ }
23
+ function buildOauthInitUrl(opts) {
24
+ const base = opts.baseUrl.replace(/\/$/, "");
25
+ const params = new URLSearchParams({
26
+ product: opts.product,
27
+ redirect_uri: opts.redirectUri,
28
+ code_challenge: opts.codeChallenge,
29
+ code_challenge_method: opts.codeChallengeMethod ?? "S256"
30
+ });
31
+ if (opts.state) params.set("state", opts.state);
32
+ return `${base}/auth/${opts.provider}?${params.toString()}`;
33
+ }
34
+
35
+ export { buildOauthInitUrl, generateOauthState, generatePkceChallenge };
36
+ //# sourceMappingURL=oauth.js.map
37
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/oauth.ts"],"names":[],"mappings":";AAEA,SAAS,qBAAqB,KAAA,EAA2B;AACrD,EAAA,IAAI,GAAA,GAAM,EAAA;AACV,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,MAAA,EAAQ,CAAA,EAAA,EAAK,GAAA,IAAO,MAAA,CAAO,YAAA,CAAa,KAAA,CAAM,CAAC,CAAW,CAAA;AACpF,EAAA,OAAO,IAAA,CAAK,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC9E;AAEA,SAAS,YAAY,MAAA,EAA4B;AAC7C,EAAA,MAAM,GAAA,GAAM,IAAI,UAAA,CAAW,MAAM,CAAA;AACjC,EAAA,UAAA,CAAW,MAAA,CAAO,gBAAgB,GAAG,CAAA;AACrC,EAAA,OAAO,GAAA;AACX;AAEA,eAAsB,qBAAA,GAAgD;AAClE,EAAA,MAAM,MAAA,GAAS,WAAW,MAAA,EAAQ,MAAA;AAClC,EAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,MAAM,6DAA6D,CAAA;AAE1F,EAAA,MAAM,QAAA,GAAW,oBAAA,CAAqB,WAAA,CAAY,EAAE,CAAC,CAAA;AACrD,EAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,QAAQ,CAAC,CAAA;AAC9E,EAAA,MAAM,SAAA,GAAY,oBAAA,CAAqB,IAAI,UAAA,CAAW,IAAI,CAAC,CAAA;AAE3D,EAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,MAAA,EAAQ,MAAA,EAAO;AACjD;AAEO,SAAS,kBAAA,GAA6B;AACzC,EAAA,OAAO,oBAAA,CAAqB,WAAA,CAAY,EAAE,CAAC,CAAA;AAC/C;AAEO,SAAS,kBAAkB,IAAA,EAAwC;AACtE,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC3C,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,CAAgB;AAAA,IAC/B,SAAS,IAAA,CAAK,OAAA;AAAA,IACd,cAAc,IAAA,CAAK,WAAA;AAAA,IACnB,gBAAgB,IAAA,CAAK,aAAA;AAAA,IACrB,qBAAA,EAAuB,KAAK,mBAAA,IAAuB;AAAA,GACtD,CAAA;AACD,EAAA,IAAI,KAAK,KAAA,EAAO,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,KAAK,KAAK,CAAA;AAE9C,EAAA,OAAO,CAAA,EAAG,IAAI,CAAA,MAAA,EAAS,IAAA,CAAK,QAAQ,CAAA,CAAA,EAAI,MAAA,CAAO,UAAU,CAAA,CAAA;AAC7D","file":"oauth.js","sourcesContent":["import type { BuildOauthInitUrlOptions, PkceChallenge } from './client-types';\n\nfunction bytesToUrlSafeBase64(bytes: Uint8Array): string {\n let bin = '';\n for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i] as number);\n return btoa(bin).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction randomBytes(length: number): Uint8Array {\n const buf = new Uint8Array(length);\n globalThis.crypto.getRandomValues(buf);\n return buf;\n}\n\nexport async function generatePkceChallenge(): Promise<PkceChallenge> {\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) throw new Error('crypto.subtle not available; cannot generate PKCE challenge');\n\n const verifier = bytesToUrlSafeBase64(randomBytes(48));\n const hash = await subtle.digest('SHA-256', new TextEncoder().encode(verifier));\n const challenge = bytesToUrlSafeBase64(new Uint8Array(hash));\n\n return { verifier, challenge, method: 'S256' };\n}\n\nexport function generateOauthState(): string {\n return bytesToUrlSafeBase64(randomBytes(24));\n}\n\nexport function buildOauthInitUrl(opts: BuildOauthInitUrlOptions): string {\n const base = opts.baseUrl.replace(/\\/$/, '');\n const params = new URLSearchParams({\n product: opts.product,\n redirect_uri: opts.redirectUri,\n code_challenge: opts.codeChallenge,\n code_challenge_method: opts.codeChallengeMethod ?? 'S256',\n });\n if (opts.state) params.set('state', opts.state);\n\n return `${base}/auth/${opts.provider}?${params.toString()}`;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akira-io/billing-js",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "TypeScript client for the Akira Billing API. Pricing, downloads, checkout helpers for landing pages and web apps.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -43,6 +43,11 @@
43
43
  "import": "./dist/license.js",
44
44
  "require": "./dist/license.cjs"
45
45
  },
46
+ "./oauth": {
47
+ "types": "./dist/oauth.d.ts",
48
+ "import": "./dist/oauth.js",
49
+ "require": "./dist/oauth.cjs"
50
+ },
46
51
  "./react": {
47
52
  "types": "./dist/react.d.ts",
48
53
  "import": "./dist/react.js",