ppussh 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.
- package/README.md +192 -0
- package/dist/accounts/index.d.ts +4 -0
- package/dist/accounts/index.d.ts.map +1 -0
- package/dist/accounts/index.js +8 -0
- package/dist/accounts/index.js.map +1 -0
- package/dist/accounts/namespace.d.ts +164 -0
- package/dist/accounts/namespace.d.ts.map +1 -0
- package/dist/accounts/namespace.js +293 -0
- package/dist/accounts/namespace.js.map +1 -0
- package/dist/accounts/types.d.ts +81 -0
- package/dist/accounts/types.d.ts.map +1 -0
- package/dist/accounts/types.js +14 -0
- package/dist/accounts/types.js.map +1 -0
- package/dist/client.d.ts +67 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +81 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +81 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +94 -0
- package/dist/errors.js.map +1 -0
- package/dist/http.d.ts +30 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +169 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/dist/payments/index.d.ts +3 -0
- package/dist/payments/index.d.ts.map +1 -0
- package/dist/payments/index.js +6 -0
- package/dist/payments/index.js.map +1 -0
- package/dist/payments/namespace.d.ts +146 -0
- package/dist/payments/namespace.d.ts.map +1 -0
- package/dist/payments/namespace.js +229 -0
- package/dist/payments/namespace.js.map +1 -0
- package/dist/payments/types.d.ts +98 -0
- package/dist/payments/types.d.ts.map +1 -0
- package/dist/payments/types.js +10 -0
- package/dist/payments/types.js.map +1 -0
- package/dist/webhooks.d.ts +56 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +67 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +54 -0
package/dist/http.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ppussh/src/http.ts
|
|
3
|
+
/**
|
|
4
|
+
* Shared HTTP transport layer for the PPUSSH TypeScript SDK.
|
|
5
|
+
*
|
|
6
|
+
* Responsibilities:
|
|
7
|
+
* - Owns an Axios instance per base URL.
|
|
8
|
+
* - Implements the retry policy:
|
|
9
|
+
* 5xx errors → up to MAX_RETRIES attempts, exponential back-off (500ms, 1s, 2s).
|
|
10
|
+
* 429 → respects Retry-After header; falls back to 1s default.
|
|
11
|
+
* 4xx (≠ 429) → never retried; raised immediately.
|
|
12
|
+
* Network errors → treated like 5xx for retry purposes.
|
|
13
|
+
* - Raises typed PpusshError subclasses; callers never see raw Axios errors.
|
|
14
|
+
*/
|
|
15
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
16
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.HttpTransport = void 0;
|
|
20
|
+
const axios_1 = __importDefault(require("axios"));
|
|
21
|
+
const errors_1 = require("./errors");
|
|
22
|
+
// ── Retry constants ──────────────────────────────────────────────────────────
|
|
23
|
+
const MAX_RETRIES = 3;
|
|
24
|
+
const BACKOFF_SCHEDULE = [500, 1000, 2000]; // ms
|
|
25
|
+
const RETRY_AFTER_DEFAULT = 1000; // ms fallback for missing Retry-After
|
|
26
|
+
const MAX_RATE_LIMIT_RETRIES = 2;
|
|
27
|
+
const SDK_USER_AGENT = "ppussh-ts/1.0.0";
|
|
28
|
+
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
29
|
+
function sleep(ms) {
|
|
30
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
31
|
+
}
|
|
32
|
+
function parseRetryAfter(headers) {
|
|
33
|
+
const raw = headers["retry-after"] ?? headers["Retry-After"];
|
|
34
|
+
if (raw !== undefined) {
|
|
35
|
+
const secs = parseFloat(raw);
|
|
36
|
+
if (!isNaN(secs))
|
|
37
|
+
return secs * 1000;
|
|
38
|
+
}
|
|
39
|
+
return RETRY_AFTER_DEFAULT;
|
|
40
|
+
}
|
|
41
|
+
function extractDetail(body) {
|
|
42
|
+
if (typeof body === "string")
|
|
43
|
+
return body;
|
|
44
|
+
if (body && typeof body === "object") {
|
|
45
|
+
const b = body;
|
|
46
|
+
return String(b["detail"] ?? b["error"] ?? b["message"] ?? "");
|
|
47
|
+
}
|
|
48
|
+
return "";
|
|
49
|
+
}
|
|
50
|
+
function raiseClientError(status, body, isPayments) {
|
|
51
|
+
// ── CONSENT_REQUIRED ───────────────────────────────────────────────────────
|
|
52
|
+
if (status === 403 &&
|
|
53
|
+
body &&
|
|
54
|
+
typeof body === "object" &&
|
|
55
|
+
body["status"] === "CONSENT_REQUIRED") {
|
|
56
|
+
const b = body;
|
|
57
|
+
throw new errors_1.PpusshConsentRequired(`User has not consented to product '${b["product_name"] ?? ""}'.`, {
|
|
58
|
+
clientId: String(b["client_id"] ?? ""),
|
|
59
|
+
productName: String(b["product_name"] ?? ""),
|
|
60
|
+
productDescription: String(b["product_description"] ?? ""),
|
|
61
|
+
statusCode: 403,
|
|
62
|
+
responseBody: body,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
// ── 401 ───────────────────────────────────────────────────────────────────
|
|
66
|
+
if (status === 401) {
|
|
67
|
+
throw new errors_1.PpusshAuthError(extractDetail(body) || "Authentication failed (HTTP 401).", {
|
|
68
|
+
statusCode: 401,
|
|
69
|
+
responseBody: body,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
// ── Payments errors ───────────────────────────────────────────────────────
|
|
73
|
+
if (isPayments) {
|
|
74
|
+
const b = body && typeof body === "object" ? body : {};
|
|
75
|
+
throw new errors_1.PpusshPaymentError(String(b["message"] ?? `Payments error (HTTP ${status}).`), {
|
|
76
|
+
code: b["code"] ? String(b["code"]) : null,
|
|
77
|
+
statusCode: status,
|
|
78
|
+
responseBody: body,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// ── Generic ───────────────────────────────────────────────────────────────
|
|
82
|
+
throw new errors_1.PpusshError(extractDetail(body) || `Request failed (HTTP ${status}).`, {
|
|
83
|
+
statusCode: status,
|
|
84
|
+
responseBody: body,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
// ── HttpTransport ─────────────────────────────────────────────────────────────
|
|
88
|
+
class HttpTransport {
|
|
89
|
+
constructor(baseUrl) {
|
|
90
|
+
this._client = axios_1.default.create({
|
|
91
|
+
baseURL: baseUrl.replace(/\/$/, ""),
|
|
92
|
+
timeout: 30000,
|
|
93
|
+
headers: {
|
|
94
|
+
"User-Agent": SDK_USER_AGENT,
|
|
95
|
+
Accept: "application/json",
|
|
96
|
+
},
|
|
97
|
+
// Never throw on non-2xx — we handle status codes ourselves
|
|
98
|
+
validateStatus: () => true,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async request(method, path, options = {}) {
|
|
102
|
+
const { headers, json, form, params, isPayments = false } = options;
|
|
103
|
+
const config = {
|
|
104
|
+
method,
|
|
105
|
+
url: path,
|
|
106
|
+
params,
|
|
107
|
+
headers: { ...headers },
|
|
108
|
+
};
|
|
109
|
+
if (json !== undefined) {
|
|
110
|
+
config.data = json;
|
|
111
|
+
config.headers["Content-Type"] = "application/json";
|
|
112
|
+
}
|
|
113
|
+
else if (form !== undefined) {
|
|
114
|
+
config.data = new URLSearchParams(form).toString();
|
|
115
|
+
config.headers["Content-Type"] =
|
|
116
|
+
"application/x-www-form-urlencoded";
|
|
117
|
+
}
|
|
118
|
+
let attempt = 0;
|
|
119
|
+
let rateLimitAttempt = 0;
|
|
120
|
+
let lastError = null;
|
|
121
|
+
while (attempt < MAX_RETRIES) {
|
|
122
|
+
let response;
|
|
123
|
+
try {
|
|
124
|
+
response = await this._client.request(config);
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
// Network / connection error
|
|
128
|
+
lastError = err;
|
|
129
|
+
attempt++;
|
|
130
|
+
if (attempt < MAX_RETRIES) {
|
|
131
|
+
const delay = BACKOFF_SCHEDULE[Math.min(attempt - 1, BACKOFF_SCHEDULE.length - 1)] ?? 2000;
|
|
132
|
+
await sleep(delay);
|
|
133
|
+
}
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const status = response.status;
|
|
137
|
+
// ── 429 Rate limited ─────────────────────────────────────────────────
|
|
138
|
+
if (status === 429) {
|
|
139
|
+
if (rateLimitAttempt >= MAX_RATE_LIMIT_RETRIES) {
|
|
140
|
+
throw new errors_1.PpusshNetworkError(`Rate limited on ${method} ${path} after ${rateLimitAttempt + 1} attempts.`, { statusCode: 429, responseBody: response.data });
|
|
141
|
+
}
|
|
142
|
+
const delay = parseRetryAfter(response.headers);
|
|
143
|
+
await sleep(delay);
|
|
144
|
+
rateLimitAttempt++;
|
|
145
|
+
continue; // does NOT consume from MAX_RETRIES
|
|
146
|
+
}
|
|
147
|
+
// ── 5xx Server error ─────────────────────────────────────────────────
|
|
148
|
+
if (status >= 500) {
|
|
149
|
+
attempt++;
|
|
150
|
+
if (attempt < MAX_RETRIES) {
|
|
151
|
+
const delay = BACKOFF_SCHEDULE[Math.min(attempt - 1, BACKOFF_SCHEDULE.length - 1)] ?? 2000;
|
|
152
|
+
await sleep(delay);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
throw new errors_1.PpusshNetworkError(`Server error ${status} on ${method} ${path} after ${MAX_RETRIES} attempts.`, { statusCode: status, responseBody: response.data });
|
|
156
|
+
}
|
|
157
|
+
// ── 4xx Client errors (not retried) ──────────────────────────────────
|
|
158
|
+
if (status >= 400) {
|
|
159
|
+
raiseClientError(status, response.data, isPayments);
|
|
160
|
+
}
|
|
161
|
+
// ── 2xx success ───────────────────────────────────────────────────────
|
|
162
|
+
return response;
|
|
163
|
+
}
|
|
164
|
+
// Fell through via network errors
|
|
165
|
+
throw new errors_1.PpusshNetworkError(`All ${MAX_RETRIES} attempts failed for ${method} ${path}.`, { cause: lastError });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
exports.HttpTransport = HttpTransport;
|
|
169
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PPUSSH TypeScript SDK — public API surface.
|
|
3
|
+
*
|
|
4
|
+
* Quick start:
|
|
5
|
+
*
|
|
6
|
+
* import { PpusshClient } from "ppussh";
|
|
7
|
+
*
|
|
8
|
+
* const client = new PpusshClient({
|
|
9
|
+
* clientId: "your-client-id",
|
|
10
|
+
* clientSecret: "your-client-secret",
|
|
11
|
+
* paymentsAdminKey: "your-payments-admin-key", // optional
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* // Build the login redirect URL
|
|
15
|
+
* const loginUrl = client.accounts.buildLoginUrl(redirectUri, state);
|
|
16
|
+
*
|
|
17
|
+
* // OIDC callback
|
|
18
|
+
* const token = await client.accounts.exchangeCode(code, redirectUri);
|
|
19
|
+
*
|
|
20
|
+
* // Middleware token check
|
|
21
|
+
* const result = await client.accounts.verifyToken(bearer);
|
|
22
|
+
*
|
|
23
|
+
* // Billing
|
|
24
|
+
* const customer = await client.payments.createCustomer(token.user.id);
|
|
25
|
+
*
|
|
26
|
+
* All errors are subclasses of PpusshError:
|
|
27
|
+
*
|
|
28
|
+
* import { PpusshError, PpusshAuthError, PpusshConsentRequired } from "ppussh";
|
|
29
|
+
*
|
|
30
|
+
* Webhook signature verification:
|
|
31
|
+
*
|
|
32
|
+
* import { verifyWebhook, WebhookEvent } from "ppussh";
|
|
33
|
+
*
|
|
34
|
+
* if (!verifyWebhook(rawBody, signatureHeader, clientSecret)) {
|
|
35
|
+
* return res.status(401).send("Invalid signature");
|
|
36
|
+
* }
|
|
37
|
+
* const event: WebhookEvent = JSON.parse(rawBody);
|
|
38
|
+
*/
|
|
39
|
+
export { PpusshClient } from "./client";
|
|
40
|
+
export type { PpusshClientOptions } from "./client";
|
|
41
|
+
export { PpusshAuthError, PpusshConsentRequired, PpusshError, PpusshNetworkError, PpusshPaymentError, } from "./errors";
|
|
42
|
+
export type { EntitlementResponse, LogoutResult, SessionResponse, TokenResponse, UserInToken, UserProfile, VerifyTokenResult, } from "./accounts/types";
|
|
43
|
+
export { effectiveAccessToken } from "./accounts/types";
|
|
44
|
+
export type { CustomerCreateRequest, CustomerResponse, MRRByPlan, MRRByProduct, MRRResponse, PaymentProductResponse, PlanResponse, SubscriptionCancelRequest, SubscriptionCreateRequest, SubscriptionListResponse, SubscriptionResponse, SubscriptionStatus, } from "./payments/types";
|
|
45
|
+
export { verifyWebhook } from "./webhooks";
|
|
46
|
+
export type { WebhookEvent, WebhookEventType } from "./webhooks";
|
|
47
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAGpD,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,WAAW,EACX,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,UAAU,CAAC;AAGlB,YAAY,EACV,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,aAAa,EACb,WAAW,EACX,WAAW,EACX,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGxD,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,WAAW,EACX,sBAAsB,EACtB,YAAY,EACZ,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ppussh/src/index.ts
|
|
3
|
+
/**
|
|
4
|
+
* PPUSSH TypeScript SDK — public API surface.
|
|
5
|
+
*
|
|
6
|
+
* Quick start:
|
|
7
|
+
*
|
|
8
|
+
* import { PpusshClient } from "ppussh";
|
|
9
|
+
*
|
|
10
|
+
* const client = new PpusshClient({
|
|
11
|
+
* clientId: "your-client-id",
|
|
12
|
+
* clientSecret: "your-client-secret",
|
|
13
|
+
* paymentsAdminKey: "your-payments-admin-key", // optional
|
|
14
|
+
* });
|
|
15
|
+
*
|
|
16
|
+
* // Build the login redirect URL
|
|
17
|
+
* const loginUrl = client.accounts.buildLoginUrl(redirectUri, state);
|
|
18
|
+
*
|
|
19
|
+
* // OIDC callback
|
|
20
|
+
* const token = await client.accounts.exchangeCode(code, redirectUri);
|
|
21
|
+
*
|
|
22
|
+
* // Middleware token check
|
|
23
|
+
* const result = await client.accounts.verifyToken(bearer);
|
|
24
|
+
*
|
|
25
|
+
* // Billing
|
|
26
|
+
* const customer = await client.payments.createCustomer(token.user.id);
|
|
27
|
+
*
|
|
28
|
+
* All errors are subclasses of PpusshError:
|
|
29
|
+
*
|
|
30
|
+
* import { PpusshError, PpusshAuthError, PpusshConsentRequired } from "ppussh";
|
|
31
|
+
*
|
|
32
|
+
* Webhook signature verification:
|
|
33
|
+
*
|
|
34
|
+
* import { verifyWebhook, WebhookEvent } from "ppussh";
|
|
35
|
+
*
|
|
36
|
+
* if (!verifyWebhook(rawBody, signatureHeader, clientSecret)) {
|
|
37
|
+
* return res.status(401).send("Invalid signature");
|
|
38
|
+
* }
|
|
39
|
+
* const event: WebhookEvent = JSON.parse(rawBody);
|
|
40
|
+
*/
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.verifyWebhook = exports.effectiveAccessToken = exports.PpusshPaymentError = exports.PpusshNetworkError = exports.PpusshError = exports.PpusshConsentRequired = exports.PpusshAuthError = exports.PpusshClient = void 0;
|
|
43
|
+
// ── Client ───────────────────────────────────────────────────────────────────
|
|
44
|
+
var client_1 = require("./client");
|
|
45
|
+
Object.defineProperty(exports, "PpusshClient", { enumerable: true, get: function () { return client_1.PpusshClient; } });
|
|
46
|
+
// ── Errors ───────────────────────────────────────────────────────────────────
|
|
47
|
+
var errors_1 = require("./errors");
|
|
48
|
+
Object.defineProperty(exports, "PpusshAuthError", { enumerable: true, get: function () { return errors_1.PpusshAuthError; } });
|
|
49
|
+
Object.defineProperty(exports, "PpusshConsentRequired", { enumerable: true, get: function () { return errors_1.PpusshConsentRequired; } });
|
|
50
|
+
Object.defineProperty(exports, "PpusshError", { enumerable: true, get: function () { return errors_1.PpusshError; } });
|
|
51
|
+
Object.defineProperty(exports, "PpusshNetworkError", { enumerable: true, get: function () { return errors_1.PpusshNetworkError; } });
|
|
52
|
+
Object.defineProperty(exports, "PpusshPaymentError", { enumerable: true, get: function () { return errors_1.PpusshPaymentError; } });
|
|
53
|
+
var types_1 = require("./accounts/types");
|
|
54
|
+
Object.defineProperty(exports, "effectiveAccessToken", { enumerable: true, get: function () { return types_1.effectiveAccessToken; } });
|
|
55
|
+
// ── Webhooks ──────────────────────────────────────────────────────────────────
|
|
56
|
+
var webhooks_1 = require("./webhooks");
|
|
57
|
+
Object.defineProperty(exports, "verifyWebhook", { enumerable: true, get: function () { return webhooks_1.verifyWebhook; } });
|
|
58
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,sBAAsB;AACtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;;;AAEH,gFAAgF;AAChF,mCAAwC;AAA/B,sGAAA,YAAY,OAAA;AAGrB,gFAAgF;AAChF,mCAMkB;AALhB,yGAAA,eAAe,OAAA;AACf,+GAAA,qBAAqB,OAAA;AACrB,qGAAA,WAAW,OAAA;AACX,4GAAA,kBAAkB,OAAA;AAClB,4GAAA,kBAAkB,OAAA;AAapB,0CAAwD;AAA/C,6GAAA,oBAAoB,OAAA;AAkB7B,iFAAiF;AACjF,uCAA2C;AAAlC,yGAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export type { CustomerCreateRequest, CustomerResponse, MRRByPlan, MRRByProduct, MRRResponse, PaymentProductResponse, PlanResponse, SubscriptionCancelRequest, SubscriptionCreateRequest, SubscriptionListResponse, SubscriptionResponse, SubscriptionStatus, } from "./types";
|
|
2
|
+
export { PaymentsNamespace } from "./namespace";
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/payments/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,WAAW,EACX,sBAAsB,EACtB,YAAY,EACZ,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PaymentsNamespace = void 0;
|
|
4
|
+
var namespace_1 = require("./namespace");
|
|
5
|
+
Object.defineProperty(exports, "PaymentsNamespace", { enumerable: true, get: function () { return namespace_1.PaymentsNamespace; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/payments/index.ts"],"names":[],"mappings":";;;AAeA,yCAAgD;AAAvC,8GAAA,iBAAiB,OAAA"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PaymentsNamespace — customer, subscription, and plan operations.
|
|
3
|
+
*
|
|
4
|
+
* Auth model:
|
|
5
|
+
* - Customer + subscription endpoints (POST /customers, POST /subscriptions, etc.)
|
|
6
|
+
* are unauthenticated at the HTTP level — the Payments service validates the
|
|
7
|
+
* owner_user_id against Accounts internally.
|
|
8
|
+
* - Admin endpoints (listPlans, getMrr) require the payments ADMIN_API_KEY
|
|
9
|
+
* sent as the `X-Admin-Key` header. Set once at PpusshClient construction
|
|
10
|
+
* time via `paymentsAdminKey`.
|
|
11
|
+
*
|
|
12
|
+
* Idempotency:
|
|
13
|
+
* - createSubscription() requires a caller-supplied idempotencyKey.
|
|
14
|
+
* Retry with the *same* key after a 502 — the server guarantees exactly-once creation.
|
|
15
|
+
* - createCustomer() is idempotent on (owner_user_id, workspace_id) — no key needed.
|
|
16
|
+
*/
|
|
17
|
+
import { HttpTransport } from "../http";
|
|
18
|
+
import { CustomerResponse, MRRResponse, PaymentProductResponse, PlanResponse, SubscriptionListResponse, SubscriptionResponse } from "./types";
|
|
19
|
+
export declare class PaymentsNamespace {
|
|
20
|
+
private readonly _http;
|
|
21
|
+
private readonly _adminKey;
|
|
22
|
+
constructor(transport: HttpTransport, options?: {
|
|
23
|
+
adminKey?: string | null;
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* Create (or retrieve) a Payments customer for a PPUSSH user.
|
|
27
|
+
*
|
|
28
|
+
* Idempotent on (owner_user_id, workspace_id) — if a customer already exists
|
|
29
|
+
* for that pair, the existing record is returned without creating a duplicate.
|
|
30
|
+
*
|
|
31
|
+
* @param ownerUserId UUID string of the Accounts user (from TokenResponse.user.id).
|
|
32
|
+
* @param workspaceId UUID string of the workspace, or null for a personal account.
|
|
33
|
+
* @param billingEmail Optional billing email — falls back to the user's account email.
|
|
34
|
+
* @param metadata Arbitrary key/value pairs stored alongside the customer record.
|
|
35
|
+
* @throws PpusshPaymentError code="accounts_user_not_found" if ownerUserId doesn't exist.
|
|
36
|
+
*/
|
|
37
|
+
createCustomer(ownerUserId: string, options?: {
|
|
38
|
+
workspaceId?: string | null;
|
|
39
|
+
billingEmail?: string | null;
|
|
40
|
+
metadata?: Record<string, unknown> | null;
|
|
41
|
+
}): Promise<CustomerResponse>;
|
|
42
|
+
/**
|
|
43
|
+
* Retrieve a Payments customer by their Payments UUID.
|
|
44
|
+
*
|
|
45
|
+
* @throws PpusshPaymentError code="customer_not_found" on 404.
|
|
46
|
+
*/
|
|
47
|
+
getCustomer(customerId: string): Promise<CustomerResponse>;
|
|
48
|
+
/**
|
|
49
|
+
* Create a subscription for a customer on a billing plan.
|
|
50
|
+
*
|
|
51
|
+
* The idempotencyKey guarantees exactly-once creation. On a provider error (502),
|
|
52
|
+
* retry with the **same key** — this is safe.
|
|
53
|
+
*
|
|
54
|
+
* @param customerId UUID from createCustomer().
|
|
55
|
+
* @param paymentProductId UUID of the PaymentProduct (from the admin console).
|
|
56
|
+
* @param planKey Plan identifier, e.g. "pro" or "enterprise".
|
|
57
|
+
* @param idempotencyKey Unique string per subscription attempt (use UUID v4).
|
|
58
|
+
* @param provider "paddle" | "dodo" | null (uses plan default).
|
|
59
|
+
* @param metadata Arbitrary key/value pairs.
|
|
60
|
+
* @throws PpusshPaymentError Various codes; see error.code for specifics.
|
|
61
|
+
*/
|
|
62
|
+
createSubscription(options: {
|
|
63
|
+
customerId: string;
|
|
64
|
+
paymentProductId: string;
|
|
65
|
+
planKey: string;
|
|
66
|
+
idempotencyKey: string;
|
|
67
|
+
provider?: string | null;
|
|
68
|
+
metadata?: Record<string, unknown> | null;
|
|
69
|
+
}): Promise<SubscriptionResponse>;
|
|
70
|
+
/**
|
|
71
|
+
* List subscriptions for a customer, with optional status filter.
|
|
72
|
+
*
|
|
73
|
+
* @param customerId UUID string.
|
|
74
|
+
* @param status Filter by status: "active", "cancelled", "trialing", etc.
|
|
75
|
+
* @param page 1-indexed page number (default 1).
|
|
76
|
+
* @param pageSize Number of results per page, max 100 (default 20).
|
|
77
|
+
*/
|
|
78
|
+
listSubscriptions(customerId: string, options?: {
|
|
79
|
+
status?: string;
|
|
80
|
+
page?: number;
|
|
81
|
+
pageSize?: number;
|
|
82
|
+
}): Promise<SubscriptionListResponse>;
|
|
83
|
+
/**
|
|
84
|
+
* Retrieve a single subscription by its Payments UUID.
|
|
85
|
+
*
|
|
86
|
+
* @throws PpusshPaymentError code="subscription_not_found" on 404.
|
|
87
|
+
*/
|
|
88
|
+
getSubscription(subscriptionId: string): Promise<SubscriptionResponse>;
|
|
89
|
+
/**
|
|
90
|
+
* Cancel a subscription.
|
|
91
|
+
*
|
|
92
|
+
* Idempotent — cancelling an already-cancelled subscription returns the
|
|
93
|
+
* existing record without error.
|
|
94
|
+
*
|
|
95
|
+
* @param subscriptionId UUID string.
|
|
96
|
+
* @param cancelImmediately If true, cancel at once.
|
|
97
|
+
* If false (default), cancel at end of current billing period.
|
|
98
|
+
*/
|
|
99
|
+
cancelSubscription(subscriptionId: string, options?: {
|
|
100
|
+
cancelImmediately?: boolean;
|
|
101
|
+
}): Promise<SubscriptionResponse>;
|
|
102
|
+
/**
|
|
103
|
+
* List all billing plans for a Payments product.
|
|
104
|
+
*
|
|
105
|
+
* Requires the `paymentsAdminKey` set on PpusshClient construction.
|
|
106
|
+
* Plans with status "archived" are included — filter client-side if needed.
|
|
107
|
+
*
|
|
108
|
+
* @param paymentProductId UUID string of the PaymentProduct.
|
|
109
|
+
* @throws PpusshPaymentError code="product_not_found" on 404.
|
|
110
|
+
* @throws Error If no paymentsAdminKey was provided at construction.
|
|
111
|
+
*/
|
|
112
|
+
listPlans(paymentProductId: string): Promise<PlanResponse[]>;
|
|
113
|
+
/**
|
|
114
|
+
* Look up a Payments product by its Accounts product ID.
|
|
115
|
+
*
|
|
116
|
+
* Returns null if the product has not yet been registered in Payments
|
|
117
|
+
* (HTTP 404 is treated as a non-exceptional "not registered yet" state).
|
|
118
|
+
*
|
|
119
|
+
* @throws Error If no paymentsAdminKey was provided at construction.
|
|
120
|
+
*/
|
|
121
|
+
getProductByAccountsId(accountsProductId: string): Promise<PaymentProductResponse | null>;
|
|
122
|
+
/**
|
|
123
|
+
* Fetch Monthly Recurring Revenue breakdown.
|
|
124
|
+
*
|
|
125
|
+
* Requires `paymentsAdminKey`.
|
|
126
|
+
*
|
|
127
|
+
* @param productId Filter to a specific product UUID (optional).
|
|
128
|
+
* @param startDate ISO date string e.g. "2025-01-01" (optional).
|
|
129
|
+
* @param endDate ISO date string e.g. "2025-12-31" (optional).
|
|
130
|
+
*/
|
|
131
|
+
getMrr(options?: {
|
|
132
|
+
productId?: string;
|
|
133
|
+
startDate?: string;
|
|
134
|
+
endDate?: string;
|
|
135
|
+
}): Promise<MRRResponse>;
|
|
136
|
+
/**
|
|
137
|
+
* Generate a hosted billing portal URL for a customer.
|
|
138
|
+
*
|
|
139
|
+
* @throws Error This feature is not yet implemented in the Payments backend.
|
|
140
|
+
*/
|
|
141
|
+
getBillingPortal(_customerId: string, _options?: {
|
|
142
|
+
returnUrl?: string;
|
|
143
|
+
}): Promise<string>;
|
|
144
|
+
private _requireAdminKey;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=namespace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namespace.d.ts","sourceRoot":"","sources":["../../src/payments/namespace.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAEL,gBAAgB,EAChB,WAAW,EACX,sBAAsB,EACtB,YAAY,EACZ,wBAAwB,EACxB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAEjB,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;gBAE9B,SAAS,EAAE,aAAa,EAAE,OAAO,GAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAO;IAOhF;;;;;;;;;;;OAWG;IACG,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QACP,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;KACtC,GACL,OAAO,CAAC,gBAAgB,CAAC;IAc5B;;;;OAIG;IACG,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAShE;;;;;;;;;;;;;OAaG;IACG,kBAAkB,CAAC,OAAO,EAAE;QAChC,UAAU,EAAE,MAAM,CAAC;QACnB,gBAAgB,EAAE,MAAM,CAAC;QACzB,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;KAC3C,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAejC;;;;;;;OAOG;IACG,iBAAiB,CACrB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACd,GACL,OAAO,CAAC,wBAAwB,CAAC;IAepC;;;;OAIG;IACG,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAS5E;;;;;;;;;OASG;IACG,kBAAkB,CACtB,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAAO,GAC5C,OAAO,CAAC,oBAAoB,CAAC;IAchC;;;;;;;;;OASG;IACG,SAAS,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAalE;;;;;;;OAOG;IACG,sBAAsB,CAC1B,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IAsBzC;;;;;;;;OAQG;IACG,MAAM,CAAC,OAAO,GAAE;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KACb,GAAG,OAAO,CAAC,WAAW,CAAC;IAiB7B;;;;OAIG;IACG,gBAAgB,CACpB,WAAW,EAAE,MAAM,EACnB,QAAQ,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO,GACpC,OAAO,CAAC,MAAM,CAAC;IASlB,OAAO,CAAC,gBAAgB;CAQzB"}
|