@duabalabs/dps-client 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,128 +1,37 @@
1
1
  /**
2
- * @duabalabs/dps-client — typed client for DPS unified checkout cloud functions.
2
+ * @duabalabs/dps-client — typed client for the DPS subscription registry.
3
+ *
4
+ * As of v0.2.0 the payment / checkout surface has been REMOVED from this
5
+ * client. All money-creation flows (donations, subscriptions, invoices,
6
+ * product checkout) now live in @duabalabs/sellub-client and are served
7
+ * by sellub-server. DPS only owns the cross-app subscription registry —
8
+ * a read-only Parse object fed by Sellub→DPS webhooks and consumed by
9
+ * the per-app subscription gates.
3
10
  *
4
11
  * Two consumption modes:
5
12
  *
6
13
  * 1. Browser / public clients (uses Parse JS SDK + a JS key):
7
14
  * const dps = createDpsClient({ Parse });
8
- * await dps.createCheckout({ ... });
15
+ * await dps.checkSubscription({ appId, email });
9
16
  *
10
- * 2. Server-side / trusted callers (uses fetch + master key — never ship
11
- * master key to the browser):
12
- * const dps = createDpsServerClient({
13
- * serverUrl: process.env.DPS_PARSE_URL,
14
- * appId: process.env.DPS_APP_ID,
15
- * masterKey: process.env.DPS_MASTER_KEY,
16
- * });
17
- * await dps.createCheckout({ ... });
17
+ * 2. Server-side / trusted callers (uses fetch + master key):
18
+ * const dps = createDpsServerClient({ serverUrl, appId, masterKey });
19
+ * await dps.checkSubscription({ appId, email });
18
20
  *
19
21
  * Both expose the same method surface and the same response types.
20
22
  */
21
- export type CheckoutFlow = "vendure" | "direct";
22
- export type CheckoutStatus = "pending" | "awaiting_payment" | "paid" | "fulfilled" | "cancelled" | "failed" | "refunded";
23
- export type OrderStatus = CheckoutStatus;
24
- export interface CheckoutCustomer {
25
- email: string;
26
- firstName?: string;
27
- lastName?: string;
28
- phone?: string;
29
- parseUserId?: string;
30
- vendureCustomerId?: string;
31
- }
32
- export interface CheckoutLineItem {
33
- productVariantId?: string;
34
- sku?: string;
35
- name: string;
36
- quantity: number;
37
- unitPrice: number;
38
- metadata?: Record<string, unknown>;
39
- }
40
- export interface PaystackSplitConfig {
41
- type: "percentage" | "flat";
42
- bearer?: "account" | "subaccount" | "all-proportional" | "all";
43
- subaccounts: Array<{
44
- subaccountCode: string;
45
- share: number;
46
- }>;
47
- }
48
- export interface CreateCheckoutInput {
49
- appId: string;
50
- storeId: string;
51
- flow: CheckoutFlow;
52
- channelToken?: string;
53
- customer: CheckoutCustomer;
54
- currency: string;
55
- amount?: number;
56
- lineItems?: CheckoutLineItem[];
57
- metadata?: Record<string, unknown>;
58
- callbackUrl?: string;
59
- splitConfig?: PaystackSplitConfig;
60
- paystackPlanCode?: string;
61
- referencePrefix?: string;
62
- }
63
- export interface CheckoutSession {
64
- checkoutId: string;
65
- orderId: string;
66
- paymentReference: string;
67
- checkoutUrl: string;
68
- accessCode?: string;
69
- status: CheckoutStatus;
70
- appId: string;
71
- flow: CheckoutFlow;
72
- storeId: string;
73
- amount: number;
74
- currency: string;
75
- expiresAt?: string;
76
- }
77
- export interface OrderRecord {
78
- id: string;
79
- appId: string;
80
- storeId: string;
81
- flow: CheckoutFlow;
82
- status: OrderStatus;
83
- amount: number;
84
- currency: string;
85
- vendureOrderId?: string;
86
- vendureOrderCode?: string;
87
- channelToken?: string;
88
- customerEmail: string;
89
- userId?: string;
90
- lineItems?: CheckoutLineItem[];
91
- metadata?: Record<string, unknown>;
92
- createdAt: string;
93
- updatedAt: string;
94
- }
95
- export interface ListOrdersInput {
96
- storeId: string;
97
- appId?: string;
98
- flow?: CheckoutFlow;
99
- limit?: number;
100
- skip?: number;
101
- }
102
- export interface PaymentVerification {
103
- status: "success" | "failed" | "abandoned" | "pending" | string;
104
- reference: string;
105
- amount: number;
106
- currency: string;
107
- raw: Record<string, unknown>;
108
- }
109
23
  export interface SubscriptionStatus {
110
24
  active: boolean;
111
25
  tier: string | null;
112
26
  expiresAt: string | null;
113
27
  orderId: string | null;
114
28
  }
29
+ export interface CheckSubscriptionInput {
30
+ appId: string;
31
+ email: string;
32
+ }
115
33
  export interface DpsClient {
116
- createCheckout(input: CreateCheckoutInput): Promise<CheckoutSession>;
117
- getCheckout(checkoutId: string): Promise<CheckoutSession | null>;
118
- cancelCheckout(checkoutId: string): Promise<CheckoutSession | null>;
119
- getOrder(orderId: string): Promise<OrderRecord | null>;
120
- listOrders(input: ListOrdersInput): Promise<OrderRecord[]>;
121
- verifyPayment(reference: string): Promise<PaymentVerification>;
122
- checkSubscription(input: {
123
- appId: string;
124
- email: string;
125
- }): Promise<SubscriptionStatus>;
34
+ checkSubscription(input: CheckSubscriptionInput): Promise<SubscriptionStatus>;
126
35
  }
127
36
  export interface ParseLike {
128
37
  Cloud: {
@@ -140,4 +49,3 @@ export interface ServerClientOptions {
140
49
  fetch?: typeof fetch;
141
50
  }
142
51
  export declare function createDpsServerClient(opts: ServerClientOptions): DpsClient;
143
- export { withTenant, type TenantConfig, type TenantClient, type DonationCheckoutInput, type SubscriptionCheckoutInput, type InvoiceCheckoutInput, type ProductCheckoutInput, } from "./tenant";
package/dist/index.js CHANGED
@@ -1,20 +1,22 @@
1
1
  /**
2
- * @duabalabs/dps-client — typed client for DPS unified checkout cloud functions.
2
+ * @duabalabs/dps-client — typed client for the DPS subscription registry.
3
+ *
4
+ * As of v0.2.0 the payment / checkout surface has been REMOVED from this
5
+ * client. All money-creation flows (donations, subscriptions, invoices,
6
+ * product checkout) now live in @duabalabs/sellub-client and are served
7
+ * by sellub-server. DPS only owns the cross-app subscription registry —
8
+ * a read-only Parse object fed by Sellub→DPS webhooks and consumed by
9
+ * the per-app subscription gates.
3
10
  *
4
11
  * Two consumption modes:
5
12
  *
6
13
  * 1. Browser / public clients (uses Parse JS SDK + a JS key):
7
14
  * const dps = createDpsClient({ Parse });
8
- * await dps.createCheckout({ ... });
15
+ * await dps.checkSubscription({ appId, email });
9
16
  *
10
- * 2. Server-side / trusted callers (uses fetch + master key — never ship
11
- * master key to the browser):
12
- * const dps = createDpsServerClient({
13
- * serverUrl: process.env.DPS_PARSE_URL,
14
- * appId: process.env.DPS_APP_ID,
15
- * masterKey: process.env.DPS_MASTER_KEY,
16
- * });
17
- * await dps.createCheckout({ ... });
17
+ * 2. Server-side / trusted callers (uses fetch + master key):
18
+ * const dps = createDpsServerClient({ serverUrl, appId, masterKey });
19
+ * await dps.checkSubscription({ appId, email });
18
20
  *
19
21
  * Both expose the same method surface and the same response types.
20
22
  */
@@ -33,12 +35,7 @@ export function createDpsClient(opts) {
33
35
  return unwrap(res);
34
36
  };
35
37
  return {
36
- createCheckout: (input) => run("dps_checkout_create", input),
37
- getCheckout: (checkoutId) => run("dps_checkout_get", { checkoutId }),
38
- cancelCheckout: (checkoutId) => run("dps_checkout_cancel", { checkoutId }),
39
- getOrder: (orderId) => run("dps_orders_get", { orderId }),
40
- listOrders: (input) => run("dps_orders_list", input),
41
- verifyPayment: (reference) => run("dps_payments_verify", { reference }), checkSubscription: (input) => run("dps_subscriptions_check", input),
38
+ checkSubscription: (input) => run("dps_subscriptions_check", input),
42
39
  };
43
40
  }
44
41
  export function createDpsServerClient(opts) {
@@ -65,16 +62,6 @@ export function createDpsServerClient(opts) {
65
62
  return unwrap(json?.result);
66
63
  };
67
64
  return {
68
- createCheckout: (input) => run("dps_checkout_create", input),
69
- getCheckout: (checkoutId) => run("dps_checkout_get", { checkoutId }),
70
- cancelCheckout: (checkoutId) => run("dps_checkout_cancel", { checkoutId }),
71
- getOrder: (orderId) => run("dps_orders_get", { orderId }),
72
- listOrders: (input) => run("dps_orders_list", input),
73
- verifyPayment: (reference) => run("dps_payments_verify", { reference }),
74
65
  checkSubscription: (input) => run("dps_subscriptions_check", input),
75
66
  };
76
67
  }
77
- // ────────────────────────────────────────────────────────────────────────────
78
- // Tenant-bound helpers (donation / subscription / invoice / product)
79
- // ────────────────────────────────────────────────────────────────────────────
80
- export { withTenant, } from "./tenant";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@duabalabs/dps-client",
3
- "version": "0.1.1",
4
- "description": "Typed client for the DPS unified checkout/commerce orchestration cloud functions.",
3
+ "version": "0.2.0",
4
+ "description": "Typed client for the DPS subscription registry. Payment / checkout flows live in @duabalabs/sellub-client.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
package/dist/tenant.d.ts DELETED
@@ -1,105 +0,0 @@
1
- /**
2
- * Tenant-bound, domain-specific checkout helpers.
3
- *
4
- * These wrap the generic `DpsClient.createCheckout()` with strongly-typed
5
- * helpers for each checkout type we support across the Duabalabs ecosystem
6
- * (donations, subscriptions, invoices, …). New checkout types are added
7
- * here so every consuming app benefits without re-implementing payload
8
- * boilerplate.
9
- *
10
- * Usage (browser):
11
- *
12
- * const tenant = withTenant(createDpsClient({ Parse }), {
13
- * appId: "duabanti",
14
- * storeId: "duabanti",
15
- * referencePrefix: "DNTI",
16
- * });
17
- * await tenant.createDonation({ amount: 50, customer: { email } });
18
- *
19
- * Usage (server):
20
- *
21
- * const tenant = withTenant(createDpsServerClient({ ... }), {
22
- * appId: "duabaconnect",
23
- * storeId: "duabaconnect",
24
- * });
25
- * await tenant.startSubscription({ tier: "starter", planCode, … });
26
- */
27
- import type { DpsClient, CheckoutSession, CheckoutCustomer, CheckoutLineItem, CheckoutFlow, PaymentVerification, SubscriptionStatus, PaystackSplitConfig } from "./index";
28
- export interface TenantConfig {
29
- /** Opaque tenant tag — e.g. `duabanti`, `duabaconnect`, `duabatrade`. */
30
- appId: string;
31
- /** Sellub `storeId` for this tenant (or a tenant-specific id when not on sellub). */
32
- storeId: string;
33
- /** Optional: when set, vendure-flow checkouts can be created. */
34
- channelToken?: string;
35
- /** Optional default reference prefix passed to dps-server. */
36
- referencePrefix?: string;
37
- /** Optional default currency (ISO 4217) — defaults to `GHS`. */
38
- defaultCurrency?: string;
39
- /** Optional default Paystack split config applied when caller doesn't override. */
40
- defaultSplitConfig?: PaystackSplitConfig;
41
- }
42
- export interface DonationCheckoutInput {
43
- amount: number;
44
- currency?: string;
45
- customer: CheckoutCustomer;
46
- campaign?: string;
47
- callbackUrl?: string;
48
- metadata?: Record<string, unknown>;
49
- }
50
- export interface SubscriptionCheckoutInput {
51
- /** Free-form tier id e.g. `starter`, `growth`, `pro`. */
52
- tier: string;
53
- /** Paystack subscription plan code (server creates the subscription against this). */
54
- planCode: string;
55
- /** First charge amount in major units. */
56
- amount: number;
57
- currency?: string;
58
- customer: CheckoutCustomer;
59
- callbackUrl?: string;
60
- metadata?: Record<string, unknown>;
61
- }
62
- export interface InvoiceCheckoutInput {
63
- /** Human-facing invoice / quote reference. Stored in `metadata.reference`. */
64
- reference: string;
65
- amount: number;
66
- currency?: string;
67
- customer: CheckoutCustomer;
68
- description?: string;
69
- /** Optional explicit line items (otherwise a single line is synthesized for vendure flow). */
70
- lineItems?: CheckoutLineItem[];
71
- /** Force a flow. Defaults to `vendure` when `channelToken` is set, else `direct`. */
72
- flow?: CheckoutFlow;
73
- callbackUrl?: string;
74
- metadata?: Record<string, unknown>;
75
- }
76
- export interface ProductCheckoutInput {
77
- lineItems: CheckoutLineItem[];
78
- customer: CheckoutCustomer;
79
- currency?: string;
80
- /** Optional override; defaults to summing `lineItems`. */
81
- amount?: number;
82
- callbackUrl?: string;
83
- metadata?: Record<string, unknown>;
84
- splitConfig?: PaystackSplitConfig;
85
- }
86
- export interface TenantClient {
87
- /** Underlying generic DPS client — escape hatch for advanced calls. */
88
- readonly client: DpsClient;
89
- readonly config: Readonly<TenantConfig>;
90
- /** Charge a one-off donation through the `direct` flow. */
91
- createDonation(input: DonationCheckoutInput): Promise<CheckoutSession>;
92
- /** Start a Paystack-backed recurring subscription via the `direct` flow + plan code. */
93
- startSubscription(input: SubscriptionCheckoutInput): Promise<CheckoutSession>;
94
- /** Pay an invoice / quote (vendure when channelToken is configured, else direct). */
95
- createInvoice(input: InvoiceCheckoutInput): Promise<CheckoutSession>;
96
- /** Catalog product checkout — requires line items + a configured channel for vendure. */
97
- createProductCheckout(input: ProductCheckoutInput): Promise<CheckoutSession>;
98
- /** Verify a Paystack reference (use on thank-you / callback pages). */
99
- verifyPayment(reference: string): Promise<PaymentVerification>;
100
- /** Check whether a customer email has an active subscription with this tenant. */
101
- hasActiveSubscription(input: {
102
- email: string;
103
- }): Promise<SubscriptionStatus>;
104
- }
105
- export declare function withTenant(client: DpsClient, config: TenantConfig): TenantClient;
package/dist/tenant.js DELETED
@@ -1,151 +0,0 @@
1
- /**
2
- * Tenant-bound, domain-specific checkout helpers.
3
- *
4
- * These wrap the generic `DpsClient.createCheckout()` with strongly-typed
5
- * helpers for each checkout type we support across the Duabalabs ecosystem
6
- * (donations, subscriptions, invoices, …). New checkout types are added
7
- * here so every consuming app benefits without re-implementing payload
8
- * boilerplate.
9
- *
10
- * Usage (browser):
11
- *
12
- * const tenant = withTenant(createDpsClient({ Parse }), {
13
- * appId: "duabanti",
14
- * storeId: "duabanti",
15
- * referencePrefix: "DNTI",
16
- * });
17
- * await tenant.createDonation({ amount: 50, customer: { email } });
18
- *
19
- * Usage (server):
20
- *
21
- * const tenant = withTenant(createDpsServerClient({ ... }), {
22
- * appId: "duabaconnect",
23
- * storeId: "duabaconnect",
24
- * });
25
- * await tenant.startSubscription({ tier: "starter", planCode, … });
26
- */
27
- // ────────────────────────────────────────────────────────────────────────────
28
- // Implementation
29
- // ────────────────────────────────────────────────────────────────────────────
30
- function defaultCurrency(cfg, override) {
31
- return override || cfg.defaultCurrency || "GHS";
32
- }
33
- function baseFields(cfg) {
34
- return {
35
- appId: cfg.appId,
36
- storeId: cfg.storeId,
37
- referencePrefix: cfg.referencePrefix,
38
- };
39
- }
40
- export function withTenant(client, config) {
41
- if (!config.appId)
42
- throw new Error("withTenant: `appId` is required");
43
- if (!config.storeId)
44
- throw new Error("withTenant: `storeId` is required");
45
- const cfg = { ...config };
46
- return {
47
- client,
48
- config: cfg,
49
- createDonation(input) {
50
- const payload = {
51
- ...baseFields(cfg),
52
- flow: "direct",
53
- currency: defaultCurrency(cfg, input.currency),
54
- amount: input.amount,
55
- customer: input.customer,
56
- callbackUrl: input.callbackUrl,
57
- splitConfig: cfg.defaultSplitConfig,
58
- metadata: {
59
- type: "donation",
60
- campaign: input.campaign,
61
- source: cfg.appId,
62
- ...input.metadata,
63
- },
64
- };
65
- return client.createCheckout(payload);
66
- },
67
- startSubscription(input) {
68
- if (!input.planCode) {
69
- throw new Error(`startSubscription: planCode is required (no Paystack plan configured for tier "${input.tier}").`);
70
- }
71
- const payload = {
72
- ...baseFields(cfg),
73
- flow: "direct",
74
- currency: defaultCurrency(cfg, input.currency),
75
- amount: input.amount,
76
- customer: input.customer,
77
- paystackPlanCode: input.planCode,
78
- callbackUrl: input.callbackUrl,
79
- splitConfig: cfg.defaultSplitConfig,
80
- metadata: {
81
- type: "subscription",
82
- tier: input.tier,
83
- source: cfg.appId,
84
- ...input.metadata,
85
- },
86
- };
87
- return client.createCheckout(payload);
88
- },
89
- createInvoice(input) {
90
- const flow = input.flow || (cfg.channelToken ? "vendure" : "direct");
91
- const lineItems = input.lineItems ||
92
- (flow === "vendure"
93
- ? [
94
- {
95
- name: input.description || `Invoice ${input.reference}`,
96
- quantity: 1,
97
- unitPrice: input.amount,
98
- },
99
- ]
100
- : undefined);
101
- const payload = {
102
- ...baseFields(cfg),
103
- flow,
104
- channelToken: flow === "vendure" ? cfg.channelToken : undefined,
105
- currency: defaultCurrency(cfg, input.currency),
106
- amount: input.amount,
107
- lineItems,
108
- customer: input.customer,
109
- callbackUrl: input.callbackUrl,
110
- splitConfig: cfg.defaultSplitConfig,
111
- metadata: {
112
- type: "invoice",
113
- reference: input.reference,
114
- description: input.description,
115
- source: cfg.appId,
116
- ...input.metadata,
117
- },
118
- };
119
- return client.createCheckout(payload);
120
- },
121
- createProductCheckout(input) {
122
- const flow = cfg.channelToken ? "vendure" : "direct";
123
- if (flow === "vendure" && !cfg.channelToken) {
124
- throw new Error("createProductCheckout: vendure flow requires channelToken on TenantConfig.");
125
- }
126
- const payload = {
127
- ...baseFields(cfg),
128
- flow,
129
- channelToken: cfg.channelToken,
130
- currency: defaultCurrency(cfg, input.currency),
131
- amount: input.amount,
132
- lineItems: input.lineItems,
133
- customer: input.customer,
134
- callbackUrl: input.callbackUrl,
135
- splitConfig: input.splitConfig || cfg.defaultSplitConfig,
136
- metadata: {
137
- type: "product",
138
- source: cfg.appId,
139
- ...input.metadata,
140
- },
141
- };
142
- return client.createCheckout(payload);
143
- },
144
- verifyPayment(reference) {
145
- return client.verifyPayment(reference);
146
- },
147
- hasActiveSubscription(input) {
148
- return client.checkSubscription({ appId: cfg.appId, email: input.email });
149
- },
150
- };
151
- }