@roxyon/api-client 0.3.0 → 0.5.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.cjs +305 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +233 -2
- package/dist/index.d.ts +233 -2
- package/dist/index.js +297 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -23,13 +23,20 @@ __export(index_exports, {
|
|
|
23
23
|
AccountApi: () => AccountApi,
|
|
24
24
|
ApplicationsApi: () => ApplicationsApi,
|
|
25
25
|
AuthApi: () => AuthApi,
|
|
26
|
+
BAAS_MAX_BATCH: () => BAAS_MAX_BATCH,
|
|
27
|
+
BAAS_MAX_PAGE: () => BAAS_MAX_PAGE,
|
|
28
|
+
BILLING_CYCLES: () => BILLING_CYCLES,
|
|
29
|
+
BaasDataApi: () => BaasDataApi,
|
|
30
|
+
BillingApi: () => BillingApi,
|
|
26
31
|
DEFAULT_APP: () => DEFAULT_APP,
|
|
27
32
|
DEFAULT_BAAS_URL: () => DEFAULT_BAAS_URL,
|
|
33
|
+
DEFAULT_BAAS_V2_URL: () => DEFAULT_BAAS_V2_URL,
|
|
28
34
|
DEFAULT_CONSOLE_URL: () => DEFAULT_CONSOLE_URL,
|
|
29
35
|
DatabasesApi: () => DatabasesApi,
|
|
30
36
|
DomainsApi: () => DomainsApi,
|
|
31
37
|
EmailApi: () => EmailApi,
|
|
32
38
|
LUMEN_BUILD: () => LUMEN_BUILD,
|
|
39
|
+
PAYABLE_STATUSES: () => PAYABLE_STATUSES,
|
|
33
40
|
RUNTIMES: () => RUNTIMES,
|
|
34
41
|
Roxyon: () => Roxyon,
|
|
35
42
|
RoxyonApiError: () => RoxyonApiError,
|
|
@@ -42,6 +49,7 @@ __export(index_exports, {
|
|
|
42
49
|
envFromStored: () => envFromStored,
|
|
43
50
|
formatEnv: () => formatEnv,
|
|
44
51
|
isAuthError: () => isAuthError,
|
|
52
|
+
isPayable: () => isPayable,
|
|
45
53
|
parseEnv: () => parseEnv,
|
|
46
54
|
rxError: () => rxError,
|
|
47
55
|
toQueryString: () => toQueryString
|
|
@@ -450,6 +458,156 @@ var AuthApi = class {
|
|
|
450
458
|
}
|
|
451
459
|
};
|
|
452
460
|
|
|
461
|
+
// src/billing.ts
|
|
462
|
+
var BILLING_CYCLES = ["monthly", "quarterly", "yearly", "biennial"];
|
|
463
|
+
var RESELLER_RESOLD_SERVICE_ID = "bjMqdLqAKl";
|
|
464
|
+
var PAYABLE_STATUSES = ["pending", "overdue", "failed"];
|
|
465
|
+
function isPayable(status) {
|
|
466
|
+
return PAYABLE_STATUSES.includes(status.toLowerCase());
|
|
467
|
+
}
|
|
468
|
+
function json(v, fallback) {
|
|
469
|
+
if (v && typeof v === "object") return v;
|
|
470
|
+
if (typeof v !== "string" || v === "") return fallback;
|
|
471
|
+
try {
|
|
472
|
+
return JSON.parse(v);
|
|
473
|
+
} catch {
|
|
474
|
+
return fallback;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
function numbers(v) {
|
|
478
|
+
const out = {};
|
|
479
|
+
const src = json(v, {});
|
|
480
|
+
for (const c of BILLING_CYCLES) {
|
|
481
|
+
const n = Number(src[c]);
|
|
482
|
+
if (src[c] !== void 0 && src[c] !== "" && Number.isFinite(n)) out[c] = n;
|
|
483
|
+
}
|
|
484
|
+
return out;
|
|
485
|
+
}
|
|
486
|
+
var BillingApi = class {
|
|
487
|
+
constructor(client, pub = client.publicClient()) {
|
|
488
|
+
this.client = client;
|
|
489
|
+
this.pub = pub;
|
|
490
|
+
}
|
|
491
|
+
client;
|
|
492
|
+
pub;
|
|
493
|
+
async catalog() {
|
|
494
|
+
const r = await this.pub.get("/Plans", {
|
|
495
|
+
fields: "*",
|
|
496
|
+
limit: -1,
|
|
497
|
+
order: "objectId",
|
|
498
|
+
where: { Status: "active", Service: { nin: RESELLER_RESOLD_SERVICE_ID } },
|
|
499
|
+
include: [
|
|
500
|
+
{ className: "Services", field: "Service", fields: "Type" },
|
|
501
|
+
{
|
|
502
|
+
className: "Pricing",
|
|
503
|
+
field: "Plan",
|
|
504
|
+
fields: "Prices,SetupFee,MetaData,IsActive",
|
|
505
|
+
reverse: 1
|
|
506
|
+
}
|
|
507
|
+
]
|
|
508
|
+
});
|
|
509
|
+
if (!Array.isArray(r.results)) {
|
|
510
|
+
throw new RoxyonApiError(r.error || "Could not load the catalog.", { body: r });
|
|
511
|
+
}
|
|
512
|
+
const out = [];
|
|
513
|
+
for (const p of r.results) {
|
|
514
|
+
const pricing = p._Pricing?.results?.[0];
|
|
515
|
+
if (!p.Code || !pricing || Number(pricing.IsActive) === 0) continue;
|
|
516
|
+
const limits = json(p.Limits, {});
|
|
517
|
+
const features = json(p.Features, {});
|
|
518
|
+
const meta = json(pricing.MetaData, {});
|
|
519
|
+
const network = json(features.Network, {});
|
|
520
|
+
const setup = numbers(pricing.SetupFee);
|
|
521
|
+
const pricesUSD = numbers(pricing.Prices);
|
|
522
|
+
if (pricesUSD.monthly === void 0) continue;
|
|
523
|
+
const product = {
|
|
524
|
+
planId: p.objectId,
|
|
525
|
+
sku: p.Code ?? "",
|
|
526
|
+
name: p.Name ?? "",
|
|
527
|
+
category: p._Service?.results?.[0]?.Type ?? "",
|
|
528
|
+
pricesUSD,
|
|
529
|
+
stock: String(meta.stock ?? "in").toLowerCase() === "out" ? "out" : "in"
|
|
530
|
+
};
|
|
531
|
+
if (limits.vcpu != null) {
|
|
532
|
+
product.vcpu = Number(limits.vcpu);
|
|
533
|
+
product.ramGb = limits.memory_mb ? Math.round(Number(limits.memory_mb) / 1024) : 0;
|
|
534
|
+
product.diskGb = Number(limits.disk_gb ?? 0);
|
|
535
|
+
product.cpuType = String(limits.cpu_type ?? "");
|
|
536
|
+
}
|
|
537
|
+
if (network["Dedicated IPv4"] != null)
|
|
538
|
+
product.ipv4Included = Number(network["Dedicated IPv4"]);
|
|
539
|
+
if (Object.values(setup).some((n) => n > 0)) product.setupFeeUSD = setup;
|
|
540
|
+
if (Object.keys(features).length) product.features = features;
|
|
541
|
+
out.push(product);
|
|
542
|
+
}
|
|
543
|
+
return out;
|
|
544
|
+
}
|
|
545
|
+
/** What checkout would charge for a new subscription: the server's own pricing (GET /_payment/quote). */
|
|
546
|
+
async quote(input) {
|
|
547
|
+
if (!/^[A-Za-z0-9]{1,40}$/.test(input.planId))
|
|
548
|
+
throw new Error(`Invalid planId "${input.planId}".`);
|
|
549
|
+
if (!BILLING_CYCLES.includes(input.cycle))
|
|
550
|
+
throw new Error(`Unsupported cycle "${input.cycle}".`);
|
|
551
|
+
const q = {
|
|
552
|
+
type: "subscription.new",
|
|
553
|
+
planId: input.planId,
|
|
554
|
+
cycle: input.cycle,
|
|
555
|
+
setup: 1
|
|
556
|
+
};
|
|
557
|
+
if (input.currency) q.currency = input.currency.toUpperCase();
|
|
558
|
+
if (input.country) q.country = input.country.toUpperCase();
|
|
559
|
+
const r = await this.pub.get("/_payment/quote", q);
|
|
560
|
+
if (!r?.ok) throw new RoxyonApiError(r?.error || "Could not price this plan.", { body: r });
|
|
561
|
+
return {
|
|
562
|
+
planId: String(r.planId ?? input.planId),
|
|
563
|
+
cycle: String(r.cycle ?? input.cycle),
|
|
564
|
+
currency: String(r.currency ?? ""),
|
|
565
|
+
lineItems: (r.lineItems ?? []).map((l) => ({
|
|
566
|
+
label: l.label,
|
|
567
|
+
amount: l.amount,
|
|
568
|
+
amountUSD: l.amountUSD
|
|
569
|
+
})),
|
|
570
|
+
subtotal: String(r.subtotal ?? ""),
|
|
571
|
+
taxRate: String(r.taxRate ?? ""),
|
|
572
|
+
taxLabel: String(r.taxLabel ?? ""),
|
|
573
|
+
taxAmount: String(r.taxAmount ?? ""),
|
|
574
|
+
discountAmount: String(r.discountAmount ?? ""),
|
|
575
|
+
total: String(r.total ?? ""),
|
|
576
|
+
fxRate: String(r.fxRate ?? ""),
|
|
577
|
+
baseAmountUSD: String(r.baseAmount ?? "")
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* A new order for the caller (POST /account/order): dry run unless `confirm`. The engine prices and creates it
|
|
582
|
+
* (Subscription in payment + pending invoice); a person pays at `payUrl`. Needs a session or a PAT with the
|
|
583
|
+
* `billing:order` scope, within that token's monthly budget and allowed SKUs.
|
|
584
|
+
*/
|
|
585
|
+
async order(input) {
|
|
586
|
+
const r = await this.client.console("POST", "/account/order", { body: input, tolerateHttpError: true });
|
|
587
|
+
if (!r?.ok) throw new RoxyonApiError(r?.error || "The order was not placed.", { body: r });
|
|
588
|
+
return r;
|
|
589
|
+
}
|
|
590
|
+
/** The caller's own subscriptions (rows they own), newest first. */
|
|
591
|
+
async subscriptions() {
|
|
592
|
+
const r = await this.client.console("GET", "/account/subscriptions", { tolerateHttpError: true });
|
|
593
|
+
if (!r?.ok) throw new RoxyonApiError(r?.error || "Could not load subscriptions.", { body: r });
|
|
594
|
+
return r.subscriptions ?? [];
|
|
595
|
+
}
|
|
596
|
+
/** The caller's own invoices, newest first. */
|
|
597
|
+
async invoices(opts = {}) {
|
|
598
|
+
const q = {};
|
|
599
|
+
if (opts.status) q.status = opts.status;
|
|
600
|
+
if (opts.limit) q.limit = String(opts.limit);
|
|
601
|
+
const r = await this.client.console(
|
|
602
|
+
"GET",
|
|
603
|
+
"/account/invoices",
|
|
604
|
+
{ tolerateHttpError: true, query: q }
|
|
605
|
+
);
|
|
606
|
+
if (!r?.ok) throw new RoxyonApiError(r?.error || "Could not load invoices.", { body: r });
|
|
607
|
+
return (r.invoices ?? []).map((i) => ({ ...i, payUrl: isPayable(i.status) ? i.payUrl : null }));
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
|
|
453
611
|
// src/constants.ts
|
|
454
612
|
var DEFAULT_BAAS_URL = "https://www.beaapis.com/1";
|
|
455
613
|
var DEFAULT_CONSOLE_URL = "https://console.roxyon.com";
|
|
@@ -499,7 +657,7 @@ function toQueryString(query) {
|
|
|
499
657
|
}
|
|
500
658
|
|
|
501
659
|
// src/client.ts
|
|
502
|
-
var RoxyonClient = class {
|
|
660
|
+
var RoxyonClient = class _RoxyonClient {
|
|
503
661
|
baseUrl;
|
|
504
662
|
consoleUrl;
|
|
505
663
|
appId;
|
|
@@ -520,6 +678,17 @@ var RoxyonClient = class {
|
|
|
520
678
|
throw new Error("No fetch implementation available (need Node >= 20 or pass opts.fetch).");
|
|
521
679
|
}
|
|
522
680
|
}
|
|
681
|
+
/** Same endpoints and app, no user credentials: for public reads (catalog, quotes)
|
|
682
|
+
* that must work for PAT callers too, whose token the BaaS does not accept. */
|
|
683
|
+
publicClient() {
|
|
684
|
+
return new _RoxyonClient({
|
|
685
|
+
baseUrl: this.baseUrl,
|
|
686
|
+
consoleUrl: this.consoleUrl,
|
|
687
|
+
appId: this.appId,
|
|
688
|
+
javascriptKey: this.javascriptKey,
|
|
689
|
+
fetch: this._fetch
|
|
690
|
+
});
|
|
691
|
+
}
|
|
523
692
|
getSessionToken() {
|
|
524
693
|
return this.sessionToken;
|
|
525
694
|
}
|
|
@@ -540,16 +709,16 @@ var RoxyonClient = class {
|
|
|
540
709
|
},
|
|
541
710
|
body: JSON.stringify({ scope: "public" })
|
|
542
711
|
});
|
|
543
|
-
const
|
|
544
|
-
if (!
|
|
712
|
+
const json2 = await res.json().catch(() => ({}));
|
|
713
|
+
if (!json2.access_token && !json2.session_token) {
|
|
545
714
|
throw new RoxyonApiError("Could not obtain an anonymous BaaS token.", {
|
|
546
715
|
status: res.status,
|
|
547
|
-
body:
|
|
716
|
+
body: json2
|
|
548
717
|
});
|
|
549
718
|
}
|
|
550
|
-
|
|
551
|
-
this.anon =
|
|
552
|
-
return
|
|
719
|
+
json2._expiresAt = Date.now() + (json2.expires_in ? json2.expires_in * 1e3 : 36e5);
|
|
720
|
+
this.anon = json2;
|
|
721
|
+
return json2;
|
|
553
722
|
}
|
|
554
723
|
/** A Personal Access Token (`roxp_…`) authenticates the console endpoints via
|
|
555
724
|
* `Authorization: Bearer`; it is not a BaaS session token. */
|
|
@@ -599,17 +768,21 @@ var RoxyonClient = class {
|
|
|
599
768
|
throw new RoxyonApiError(`Network error calling ${method} ${url}`, { body: cause });
|
|
600
769
|
}
|
|
601
770
|
const text = await res.text();
|
|
602
|
-
let
|
|
771
|
+
let json2;
|
|
603
772
|
try {
|
|
604
|
-
|
|
773
|
+
json2 = text ? JSON.parse(text) : {};
|
|
605
774
|
} catch {
|
|
606
|
-
|
|
775
|
+
const html = /^\s*</.test(text);
|
|
776
|
+
json2 = {
|
|
777
|
+
error: html ? `${method} ${path} is not available on this server yet (got a web page instead of the API).` : text || `HTTP ${res.status}`,
|
|
778
|
+
_raw: html ? "" : text
|
|
779
|
+
};
|
|
607
780
|
}
|
|
608
781
|
if (!res.ok && !opts.tolerateHttpError) {
|
|
609
|
-
const msg =
|
|
610
|
-
throw new RoxyonApiError(String(msg), { status: res.status, body:
|
|
782
|
+
const msg = json2 && typeof json2 === "object" && "error" in json2 && json2.error || `HTTP ${res.status} calling ${method} ${path}`;
|
|
783
|
+
throw new RoxyonApiError(String(msg), { status: res.status, body: json2 });
|
|
611
784
|
}
|
|
612
|
-
return
|
|
785
|
+
return json2;
|
|
613
786
|
}
|
|
614
787
|
get(path, query, opts) {
|
|
615
788
|
return this.request("GET", path, { ...opts, query });
|
|
@@ -872,7 +1045,9 @@ var TokensApi = class {
|
|
|
872
1045
|
body: {
|
|
873
1046
|
name,
|
|
874
1047
|
scopes: opts.scopes ?? ["deploy", "logs"],
|
|
875
|
-
...opts.expiresInDays ? { expiresInDays: opts.expiresInDays } : {}
|
|
1048
|
+
...opts.expiresInDays ? { expiresInDays: opts.expiresInDays } : {},
|
|
1049
|
+
...opts.monthlyBudgetUSD ? { monthlyBudgetUSD: opts.monthlyBudgetUSD } : {},
|
|
1050
|
+
...opts.allowedSkus?.length ? { allowedSkus: opts.allowedSkus } : {}
|
|
876
1051
|
},
|
|
877
1052
|
tolerateHttpError: true
|
|
878
1053
|
}
|
|
@@ -892,6 +1067,112 @@ var TokensApi = class {
|
|
|
892
1067
|
}
|
|
893
1068
|
};
|
|
894
1069
|
|
|
1070
|
+
// src/baas-data.ts
|
|
1071
|
+
var DEFAULT_BAAS_V2_URL = "https://www.beaapis.com/2";
|
|
1072
|
+
var BAAS_MAX_PAGE = 200;
|
|
1073
|
+
var BAAS_MAX_BATCH = 50;
|
|
1074
|
+
var CLASS_RE = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
|
|
1075
|
+
var ID_RE = /^[A-Za-z0-9]{1,40}$/;
|
|
1076
|
+
function checkClass(name) {
|
|
1077
|
+
if (!CLASS_RE.test(name)) throw new Error(`Invalid class name "${name}".`);
|
|
1078
|
+
return name;
|
|
1079
|
+
}
|
|
1080
|
+
function checkId(id) {
|
|
1081
|
+
if (!ID_RE.test(id)) throw new Error(`Invalid objectId "${id}".`);
|
|
1082
|
+
return id;
|
|
1083
|
+
}
|
|
1084
|
+
var BaasDataApi = class _BaasDataApi {
|
|
1085
|
+
baseUrl;
|
|
1086
|
+
secretKey;
|
|
1087
|
+
_fetch;
|
|
1088
|
+
constructor(opts) {
|
|
1089
|
+
if (!opts.secretKey.startsWith("rxsk_")) {
|
|
1090
|
+
throw new Error("BaaS V2 needs the app secret key (starts with rxsk_).");
|
|
1091
|
+
}
|
|
1092
|
+
this.secretKey = opts.secretKey;
|
|
1093
|
+
this.baseUrl = (opts.baseUrl ?? DEFAULT_BAAS_V2_URL).replace(/\/+$/, "");
|
|
1094
|
+
this._fetch = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
1095
|
+
}
|
|
1096
|
+
async call(method, path, opts = {}) {
|
|
1097
|
+
const qs = opts.query && Object.keys(opts.query).length ? `?${new URLSearchParams(opts.query)}` : "";
|
|
1098
|
+
const headers = { "x-rx-secret-key": this.secretKey };
|
|
1099
|
+
if (opts.body !== void 0) headers["content-type"] = "application/json";
|
|
1100
|
+
let res;
|
|
1101
|
+
try {
|
|
1102
|
+
res = await this._fetch(`${this.baseUrl}${path}${qs}`, {
|
|
1103
|
+
method,
|
|
1104
|
+
headers,
|
|
1105
|
+
body: opts.body === void 0 ? void 0 : JSON.stringify(opts.body)
|
|
1106
|
+
});
|
|
1107
|
+
} catch (e) {
|
|
1108
|
+
throw new RoxyonApiError(`Could not reach ${this.baseUrl}: ${e.message}`);
|
|
1109
|
+
}
|
|
1110
|
+
let body = {};
|
|
1111
|
+
try {
|
|
1112
|
+
body = await res.json() ?? {};
|
|
1113
|
+
} catch {
|
|
1114
|
+
}
|
|
1115
|
+
if (!res.ok || body.ok !== true) {
|
|
1116
|
+
const msg = body.message || body.error || `HTTP ${res.status}`;
|
|
1117
|
+
throw new RoxyonApiError(msg, { status: res.status, type: body.error, body });
|
|
1118
|
+
}
|
|
1119
|
+
return body;
|
|
1120
|
+
}
|
|
1121
|
+
static recordPath(className, id) {
|
|
1122
|
+
return `/records/${checkClass(className)}${id === void 0 ? "" : `/${checkId(id)}`}`;
|
|
1123
|
+
}
|
|
1124
|
+
async query(className, q = {}) {
|
|
1125
|
+
const limit = q.limit ?? 50;
|
|
1126
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > BAAS_MAX_PAGE) {
|
|
1127
|
+
throw new Error(`limit must be 1 to ${BAAS_MAX_PAGE}.`);
|
|
1128
|
+
}
|
|
1129
|
+
const query = { fields: q.fields || "*", limit: String(limit) };
|
|
1130
|
+
if (q.where && Object.keys(q.where).length) query.where = JSON.stringify(q.where);
|
|
1131
|
+
if (q.order) query.order = q.order;
|
|
1132
|
+
if (q.skip) query.skip = String(q.skip);
|
|
1133
|
+
if (q.count) query.count = "1";
|
|
1134
|
+
const r = await this.call("GET", _BaasDataApi.recordPath(className), { query });
|
|
1135
|
+
return {
|
|
1136
|
+
rows: r.results ?? [],
|
|
1137
|
+
...r.count !== void 0 ? { count: r.count } : {}
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
async get(className, objectId) {
|
|
1141
|
+
const r = await this.call("GET", _BaasDataApi.recordPath(className, objectId));
|
|
1142
|
+
return r.result ?? {};
|
|
1143
|
+
}
|
|
1144
|
+
/** Returns the created row as stored. */
|
|
1145
|
+
async create(className, data) {
|
|
1146
|
+
const r = await this.call("POST", _BaasDataApi.recordPath(className), { body: { data } });
|
|
1147
|
+
return r.result ?? {};
|
|
1148
|
+
}
|
|
1149
|
+
async update(className, objectId, data) {
|
|
1150
|
+
const r = await this.call("PUT", _BaasDataApi.recordPath(className, objectId), {
|
|
1151
|
+
body: { data }
|
|
1152
|
+
});
|
|
1153
|
+
return r.result ?? {};
|
|
1154
|
+
}
|
|
1155
|
+
/** The id goes in the URL path, never the body. */
|
|
1156
|
+
async delete(className, objectId) {
|
|
1157
|
+
await this.call("DELETE", _BaasDataApi.recordPath(className, objectId));
|
|
1158
|
+
}
|
|
1159
|
+
/** 1 to 50 record requests in one call; one failing doesn't stop the others. */
|
|
1160
|
+
async batch(requests) {
|
|
1161
|
+
if (requests.length < 1 || requests.length > BAAS_MAX_BATCH) {
|
|
1162
|
+
throw new Error(`A batch takes 1 to ${BAAS_MAX_BATCH} requests.`);
|
|
1163
|
+
}
|
|
1164
|
+
for (const req of requests) {
|
|
1165
|
+
const [cls, id, extra] = req.path.split("/").filter(Boolean);
|
|
1166
|
+
if (!cls || extra !== void 0)
|
|
1167
|
+
throw new Error(`Batch path "${req.path}" must be /Class or /Class/id.`);
|
|
1168
|
+
checkClass(cls);
|
|
1169
|
+
if (id !== void 0) checkId(id);
|
|
1170
|
+
}
|
|
1171
|
+
const r = await this.call("POST", "/batch", { body: { requests } });
|
|
1172
|
+
return r.results ?? [];
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1175
|
+
|
|
895
1176
|
// src/env.ts
|
|
896
1177
|
function parseEnv(text) {
|
|
897
1178
|
const out = {};
|
|
@@ -971,6 +1252,7 @@ var Roxyon = class {
|
|
|
971
1252
|
databases;
|
|
972
1253
|
email;
|
|
973
1254
|
ssh;
|
|
1255
|
+
billing;
|
|
974
1256
|
constructor(options = {}) {
|
|
975
1257
|
this.client = options instanceof RoxyonClient ? options : new RoxyonClient(options);
|
|
976
1258
|
this.auth = new AuthApi(this.client);
|
|
@@ -983,6 +1265,7 @@ var Roxyon = class {
|
|
|
983
1265
|
this.databases = new DatabasesApi(this.client);
|
|
984
1266
|
this.email = new EmailApi(this.client);
|
|
985
1267
|
this.ssh = new SshApi(this.client);
|
|
1268
|
+
this.billing = new BillingApi(this.client);
|
|
986
1269
|
}
|
|
987
1270
|
get sessionToken() {
|
|
988
1271
|
return this.client.getSessionToken();
|
|
@@ -993,13 +1276,20 @@ var Roxyon = class {
|
|
|
993
1276
|
AccountApi,
|
|
994
1277
|
ApplicationsApi,
|
|
995
1278
|
AuthApi,
|
|
1279
|
+
BAAS_MAX_BATCH,
|
|
1280
|
+
BAAS_MAX_PAGE,
|
|
1281
|
+
BILLING_CYCLES,
|
|
1282
|
+
BaasDataApi,
|
|
1283
|
+
BillingApi,
|
|
996
1284
|
DEFAULT_APP,
|
|
997
1285
|
DEFAULT_BAAS_URL,
|
|
1286
|
+
DEFAULT_BAAS_V2_URL,
|
|
998
1287
|
DEFAULT_CONSOLE_URL,
|
|
999
1288
|
DatabasesApi,
|
|
1000
1289
|
DomainsApi,
|
|
1001
1290
|
EmailApi,
|
|
1002
1291
|
LUMEN_BUILD,
|
|
1292
|
+
PAYABLE_STATUSES,
|
|
1003
1293
|
RUNTIMES,
|
|
1004
1294
|
Roxyon,
|
|
1005
1295
|
RoxyonApiError,
|
|
@@ -1012,6 +1302,7 @@ var Roxyon = class {
|
|
|
1012
1302
|
envFromStored,
|
|
1013
1303
|
formatEnv,
|
|
1014
1304
|
isAuthError,
|
|
1305
|
+
isPayable,
|
|
1015
1306
|
parseEnv,
|
|
1016
1307
|
rxError,
|
|
1017
1308
|
toQueryString
|