@proappstore/sdk 0.1.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.
@@ -0,0 +1,11 @@
1
+ import { SubscriptionApi } from './subscription.js';
2
+ import { LicenseApi } from './license.js';
3
+ import type { ProInitOptions } from './types.js';
4
+ export type { ProInitOptions, Subscription, SubscriptionStatus, CheckoutRequest, LicenseInfo, } from './types.js';
5
+ export declare class ProAppStore {
6
+ readonly subscription: SubscriptionApi;
7
+ readonly license: LicenseApi;
8
+ constructor(opts: ProInitOptions);
9
+ }
10
+ export declare function initPro(opts: ProInitOptions): ProAppStore;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,YAAY,EACV,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,qBAAa,WAAW;IACtB,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;gBAEjB,IAAI,EAAE,cAAc;CAOjC;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,WAAW,CAEzD"}
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ import { SubscriptionApi } from './subscription.js';
2
+ import { LicenseApi } from './license.js';
3
+ export class ProAppStore {
4
+ subscription;
5
+ license;
6
+ constructor(opts) {
7
+ const apiBase = opts.apiBase ?? 'https://api.proappstore.online';
8
+ const tokenFn = typeof opts.authToken === 'function' ? opts.authToken : () => opts.authToken;
9
+ this.subscription = new SubscriptionApi(opts.appId, apiBase, tokenFn);
10
+ this.license = new LicenseApi(opts.appId, apiBase, tokenFn);
11
+ }
12
+ }
13
+ export function initPro(opts) {
14
+ return new ProAppStore(opts);
15
+ }
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAW1C,MAAM,OAAO,WAAW;IACb,YAAY,CAAkB;IAC9B,OAAO,CAAa;IAE7B,YAAY,IAAoB;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,gCAAgC,CAAC;QACjE,MAAM,OAAO,GACX,OAAO,IAAI,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAmB,CAAC;QACzF,IAAI,CAAC,YAAY,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACtE,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;CACF;AAED,MAAM,UAAU,OAAO,CAAC,IAAoB;IAC1C,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { LicenseInfo } from './types.js';
2
+ export declare class LicenseApi {
3
+ private readonly appId;
4
+ private readonly apiBase;
5
+ private readonly token;
6
+ constructor(appId: string, apiBase: string, token: () => string | null);
7
+ /** Returns the license info for the signed-in user, or null. */
8
+ current(): Promise<LicenseInfo | null>;
9
+ /**
10
+ * Validate an arbitrary license key against the server. Useful for cases
11
+ * where the key is delivered out-of-band (email, manual entry).
12
+ */
13
+ validate(key: string): Promise<boolean>;
14
+ }
15
+ //# sourceMappingURL=license.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../src/license.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,qBAAa,UAAU;IAEnB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAFL,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,MAAM,GAAG,IAAI;IAG7C,gEAAgE;IAC1D,OAAO,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAY5C;;;OAGG;IACG,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAU9C"}
@@ -0,0 +1,38 @@
1
+ export class LicenseApi {
2
+ appId;
3
+ apiBase;
4
+ token;
5
+ constructor(appId, apiBase, token) {
6
+ this.appId = appId;
7
+ this.apiBase = apiBase;
8
+ this.token = token;
9
+ }
10
+ /** Returns the license info for the signed-in user, or null. */
11
+ async current() {
12
+ const token = this.token();
13
+ if (!token)
14
+ return null;
15
+ const res = await fetch(new URL(`/v1/apps/${encodeURIComponent(this.appId)}/license`, this.apiBase), { headers: { Authorization: `Bearer ${token}` } });
16
+ if (res.status === 404)
17
+ return null;
18
+ if (!res.ok)
19
+ throw new Error(`license.current failed: ${res.status}`);
20
+ return (await res.json());
21
+ }
22
+ /**
23
+ * Validate an arbitrary license key against the server. Useful for cases
24
+ * where the key is delivered out-of-band (email, manual entry).
25
+ */
26
+ async validate(key) {
27
+ const res = await fetch(new URL('/v1/license/validate', this.apiBase), {
28
+ method: 'POST',
29
+ headers: { 'Content-Type': 'application/json' },
30
+ body: JSON.stringify({ appId: this.appId, key }),
31
+ });
32
+ if (!res.ok)
33
+ return false;
34
+ const { valid } = (await res.json());
35
+ return valid;
36
+ }
37
+ }
38
+ //# sourceMappingURL=license.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license.js","sourceRoot":"","sources":["../src/license.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,UAAU;IAEF;IACA;IACA;IAHnB,YACmB,KAAa,EACb,OAAe,EACf,KAA0B;QAF1B,UAAK,GAAL,KAAK,CAAQ;QACb,YAAO,GAAP,OAAO,CAAQ;QACf,UAAK,GAAL,KAAK,CAAqB;IAC1C,CAAC;IAEJ,gEAAgE;IAChE,KAAK,CAAC,OAAO;QACX,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,IAAI,GAAG,CAAC,YAAY,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,EAC3E,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,EAAE,CAClD,CAAC;QACF,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACtE,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAgB,CAAC;IAC3C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,QAAQ,CAAC,GAAW;QACxB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,sBAAsB,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;YACrE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC;SACjD,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;QAC1B,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuB,CAAC;QAC3D,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
@@ -0,0 +1,18 @@
1
+ import type { CheckoutRequest, Subscription } from './types.js';
2
+ export declare class SubscriptionApi {
3
+ private readonly appId;
4
+ private readonly apiBase;
5
+ private readonly token;
6
+ constructor(appId: string, apiBase: string, token: () => string | null);
7
+ /** Returns the user's current subscription, or null if they have none. */
8
+ status(): Promise<Subscription | null>;
9
+ /**
10
+ * Redirects the user to a Stripe-hosted checkout for the given price.
11
+ * Returns nothing — the page navigates away.
12
+ */
13
+ openCheckout(req: CheckoutRequest): Promise<void>;
14
+ /** Redirects the user to the Stripe customer portal to manage billing. */
15
+ openPortal(returnUrl: string): Promise<void>;
16
+ private req;
17
+ }
18
+ //# sourceMappingURL=subscription.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../src/subscription.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEhE,qBAAa,eAAe;IAExB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAFL,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,MAAM,GAAG,IAAI;IAG7C,0EAA0E;IACpE,MAAM,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAO5C;;;OAGG;IACG,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvD,0EAA0E;IACpE,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAOpC,GAAG;CAalB"}
@@ -0,0 +1,54 @@
1
+ export class SubscriptionApi {
2
+ appId;
3
+ apiBase;
4
+ token;
5
+ constructor(appId, apiBase, token) {
6
+ this.appId = appId;
7
+ this.apiBase = apiBase;
8
+ this.token = token;
9
+ }
10
+ /** Returns the user's current subscription, or null if they have none. */
11
+ async status() {
12
+ const res = await this.req('GET', '/v1/subscription');
13
+ if (res.status === 404)
14
+ return null;
15
+ if (!res.ok)
16
+ throw new Error(`subscription.status failed: ${res.status}`);
17
+ return (await res.json());
18
+ }
19
+ /**
20
+ * Redirects the user to a Stripe-hosted checkout for the given price.
21
+ * Returns nothing — the page navigates away.
22
+ */
23
+ async openCheckout(req) {
24
+ const res = await this.req('POST', '/v1/checkout', req);
25
+ if (!res.ok)
26
+ throw new Error(`subscription.openCheckout failed: ${res.status}`);
27
+ const { url } = (await res.json());
28
+ window.location.assign(url);
29
+ }
30
+ /** Redirects the user to the Stripe customer portal to manage billing. */
31
+ async openPortal(returnUrl) {
32
+ const res = await this.req('POST', '/v1/portal', { returnUrl });
33
+ if (!res.ok)
34
+ throw new Error(`subscription.openPortal failed: ${res.status}`);
35
+ const { url } = (await res.json());
36
+ window.location.assign(url);
37
+ }
38
+ async req(method, path, body) {
39
+ const token = this.token();
40
+ if (!token)
41
+ throw new Error('Not signed in. Pass fas.auth.token to initPro().');
42
+ const init = {
43
+ method,
44
+ headers: {
45
+ Authorization: `Bearer ${token}`,
46
+ ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),
47
+ },
48
+ };
49
+ if (body !== undefined)
50
+ init.body = JSON.stringify(body);
51
+ return fetch(new URL(path, this.apiBase), init);
52
+ }
53
+ }
54
+ //# sourceMappingURL=subscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.js","sourceRoot":"","sources":["../src/subscription.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,eAAe;IAEP;IACA;IACA;IAHnB,YACmB,KAAa,EACb,OAAe,EACf,KAA0B;QAF1B,UAAK,GAAL,KAAK,CAAQ;QACb,YAAO,GAAP,OAAO,CAAQ;QACf,UAAK,GAAL,KAAK,CAAqB;IAC1C,CAAC;IAEJ,0EAA0E;IAC1E,KAAK,CAAC,MAAM;QACV,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;QACtD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1E,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAiB,CAAC;IAC5C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAC,GAAoB;QACrC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAChF,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAoB,CAAC;QACtD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,0EAA0E;IAC1E,KAAK,CAAC,UAAU,CAAC,SAAiB;QAChC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9E,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAoB,CAAC;QACtD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAEO,KAAK,CAAC,GAAG,CAAC,MAAc,EAAE,IAAY,EAAE,IAAc;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAChF,MAAM,IAAI,GAAgB;YACxB,MAAM;YACN,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,KAAK,EAAE;gBAChC,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtE;SACF,CAAC;QACF,IAAI,IAAI,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACzD,OAAO,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;IAClD,CAAC;CACF"}
@@ -0,0 +1,36 @@
1
+ export interface ProInitOptions {
2
+ appId: string;
3
+ /** Defaults to https://api.proappstore.online */
4
+ apiBase?: string;
5
+ /**
6
+ * Bearer token from @freeappstore/sdk. Pro builds on top of free identity —
7
+ * the user is the same; pro just adds subscription state. Pass
8
+ * `fas.auth.token` here once the free auth flow has signed the user in.
9
+ */
10
+ authToken: string | (() => string | null);
11
+ }
12
+ export type SubscriptionStatus = 'active' | 'past_due' | 'canceled' | 'incomplete';
13
+ export interface Subscription {
14
+ status: SubscriptionStatus;
15
+ tier: string;
16
+ /** Stripe price id of the active plan, or null if cancelled. */
17
+ priceId: string | null;
18
+ /** Unix ms — when the current billing period ends. */
19
+ currentPeriodEnd: number;
20
+ /** True if the user has cancelled and won't auto-renew. */
21
+ cancelAtPeriodEnd: boolean;
22
+ }
23
+ export interface CheckoutRequest {
24
+ priceId: string;
25
+ /** Where to send the user after success. Must be on an allowlisted origin. */
26
+ successUrl: string;
27
+ /** Where to send the user if they cancel checkout. */
28
+ cancelUrl: string;
29
+ }
30
+ export interface LicenseInfo {
31
+ key: string;
32
+ appId: string;
33
+ issuedAt: number;
34
+ expiresAt: number | null;
35
+ }
36
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,SAAS,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC;CAC3C;AAED,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,YAAY,CAAC;AAEnF,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,sDAAsD;IACtD,gBAAgB,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@proappstore/sdk",
3
+ "version": "0.1.0",
4
+ "description": "Browser SDK for paid apps on proappstore.online — subscriptions, license keys, premium modules.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": ["dist", "README.md"],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "typecheck": "tsc --noEmit"
19
+ },
20
+ "devDependencies": {
21
+ "typescript": "^5.7.0"
22
+ },
23
+ "sideEffects": false
24
+ }