@roxyon/api-client 0.2.0 → 0.4.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 +392 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +294 -1
- package/dist/index.d.ts +294 -1
- package/dist/index.js +381 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -23,22 +23,33 @@ __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,
|
|
35
|
+
DatabasesApi: () => DatabasesApi,
|
|
29
36
|
DomainsApi: () => DomainsApi,
|
|
37
|
+
EmailApi: () => EmailApi,
|
|
30
38
|
LUMEN_BUILD: () => LUMEN_BUILD,
|
|
39
|
+
PAYABLE_STATUSES: () => PAYABLE_STATUSES,
|
|
31
40
|
RUNTIMES: () => RUNTIMES,
|
|
32
41
|
Roxyon: () => Roxyon,
|
|
33
42
|
RoxyonApiError: () => RoxyonApiError,
|
|
34
43
|
RoxyonClient: () => RoxyonClient,
|
|
35
44
|
SitesApi: () => SitesApi,
|
|
45
|
+
SshApi: () => SshApi,
|
|
36
46
|
SubscriptionsApi: () => SubscriptionsApi,
|
|
37
47
|
TokensApi: () => TokensApi,
|
|
38
48
|
assertOk: () => assertOk,
|
|
39
49
|
envFromStored: () => envFromStored,
|
|
40
50
|
formatEnv: () => formatEnv,
|
|
41
51
|
isAuthError: () => isAuthError,
|
|
52
|
+
isPayable: () => isPayable,
|
|
42
53
|
parseEnv: () => parseEnv,
|
|
43
54
|
rxError: () => rxError,
|
|
44
55
|
toQueryString: () => toQueryString
|
|
@@ -447,6 +458,144 @@ var AuthApi = class {
|
|
|
447
458
|
}
|
|
448
459
|
};
|
|
449
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",
|
|
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 (!pricing) 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 product = {
|
|
522
|
+
planId: p.objectId,
|
|
523
|
+
sku: p.Code ?? "",
|
|
524
|
+
name: p.Name ?? "",
|
|
525
|
+
category: p._Service?.results?.[0]?.Type ?? "",
|
|
526
|
+
pricesUSD: numbers(pricing.Prices),
|
|
527
|
+
stock: String(meta.stock ?? "in").toLowerCase() === "out" ? "out" : "in"
|
|
528
|
+
};
|
|
529
|
+
if (limits.vcpu != null) {
|
|
530
|
+
product.vcpu = Number(limits.vcpu);
|
|
531
|
+
product.ramGb = limits.memory_mb ? Math.round(Number(limits.memory_mb) / 1024) : 0;
|
|
532
|
+
product.diskGb = Number(limits.disk_gb ?? 0);
|
|
533
|
+
product.cpuType = String(limits.cpu_type ?? "");
|
|
534
|
+
}
|
|
535
|
+
if (network["Dedicated IPv4"] != null)
|
|
536
|
+
product.ipv4Included = Number(network["Dedicated IPv4"]);
|
|
537
|
+
if (Object.values(setup).some((n) => n > 0)) product.setupFeeUSD = setup;
|
|
538
|
+
if (Object.keys(features).length) product.features = features;
|
|
539
|
+
out.push(product);
|
|
540
|
+
}
|
|
541
|
+
return out;
|
|
542
|
+
}
|
|
543
|
+
/** What checkout would charge for a new subscription: the server's own pricing (GET /_payment/quote). */
|
|
544
|
+
async quote(input) {
|
|
545
|
+
if (!/^[A-Za-z0-9]{1,40}$/.test(input.planId))
|
|
546
|
+
throw new Error(`Invalid planId "${input.planId}".`);
|
|
547
|
+
if (!BILLING_CYCLES.includes(input.cycle))
|
|
548
|
+
throw new Error(`Unsupported cycle "${input.cycle}".`);
|
|
549
|
+
const q = {
|
|
550
|
+
type: "subscription.new",
|
|
551
|
+
planId: input.planId,
|
|
552
|
+
cycle: input.cycle,
|
|
553
|
+
setup: 1
|
|
554
|
+
};
|
|
555
|
+
if (input.currency) q.currency = input.currency.toUpperCase();
|
|
556
|
+
if (input.country) q.country = input.country.toUpperCase();
|
|
557
|
+
const r = await this.pub.get("/_payment/quote", q);
|
|
558
|
+
if (!r?.ok) throw new RoxyonApiError(r?.error || "Could not price this plan.", { body: r });
|
|
559
|
+
return {
|
|
560
|
+
planId: String(r.planId ?? input.planId),
|
|
561
|
+
cycle: String(r.cycle ?? input.cycle),
|
|
562
|
+
currency: String(r.currency ?? ""),
|
|
563
|
+
lineItems: (r.lineItems ?? []).map((l) => ({
|
|
564
|
+
label: l.label,
|
|
565
|
+
amount: l.amount,
|
|
566
|
+
amountUSD: l.amountUSD
|
|
567
|
+
})),
|
|
568
|
+
subtotal: String(r.subtotal ?? ""),
|
|
569
|
+
taxRate: String(r.taxRate ?? ""),
|
|
570
|
+
taxLabel: String(r.taxLabel ?? ""),
|
|
571
|
+
taxAmount: String(r.taxAmount ?? ""),
|
|
572
|
+
discountAmount: String(r.discountAmount ?? ""),
|
|
573
|
+
total: String(r.total ?? ""),
|
|
574
|
+
fxRate: String(r.fxRate ?? ""),
|
|
575
|
+
baseAmountUSD: String(r.baseAmount ?? "")
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
/** The caller's own subscriptions (rows they own), newest first. */
|
|
579
|
+
async subscriptions() {
|
|
580
|
+
const r = await this.client.console("GET", "/account/subscriptions", { tolerateHttpError: true });
|
|
581
|
+
if (!r?.ok) throw new RoxyonApiError(r?.error || "Could not load subscriptions.", { body: r });
|
|
582
|
+
return r.subscriptions ?? [];
|
|
583
|
+
}
|
|
584
|
+
/** The caller's own invoices, newest first. */
|
|
585
|
+
async invoices(opts = {}) {
|
|
586
|
+
const q = {};
|
|
587
|
+
if (opts.status) q.status = opts.status;
|
|
588
|
+
if (opts.limit) q.limit = String(opts.limit);
|
|
589
|
+
const r = await this.client.console(
|
|
590
|
+
"GET",
|
|
591
|
+
"/account/invoices",
|
|
592
|
+
{ tolerateHttpError: true, query: q }
|
|
593
|
+
);
|
|
594
|
+
if (!r?.ok) throw new RoxyonApiError(r?.error || "Could not load invoices.", { body: r });
|
|
595
|
+
return (r.invoices ?? []).map((i) => ({ ...i, payUrl: isPayable(i.status) ? i.payUrl : null }));
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
|
|
450
599
|
// src/constants.ts
|
|
451
600
|
var DEFAULT_BAAS_URL = "https://www.beaapis.com/1";
|
|
452
601
|
var DEFAULT_CONSOLE_URL = "https://console.roxyon.com";
|
|
@@ -496,7 +645,7 @@ function toQueryString(query) {
|
|
|
496
645
|
}
|
|
497
646
|
|
|
498
647
|
// src/client.ts
|
|
499
|
-
var RoxyonClient = class {
|
|
648
|
+
var RoxyonClient = class _RoxyonClient {
|
|
500
649
|
baseUrl;
|
|
501
650
|
consoleUrl;
|
|
502
651
|
appId;
|
|
@@ -517,6 +666,17 @@ var RoxyonClient = class {
|
|
|
517
666
|
throw new Error("No fetch implementation available (need Node >= 20 or pass opts.fetch).");
|
|
518
667
|
}
|
|
519
668
|
}
|
|
669
|
+
/** Same endpoints and app, no user credentials: for public reads (catalog, quotes)
|
|
670
|
+
* that must work for PAT callers too, whose token the BaaS does not accept. */
|
|
671
|
+
publicClient() {
|
|
672
|
+
return new _RoxyonClient({
|
|
673
|
+
baseUrl: this.baseUrl,
|
|
674
|
+
consoleUrl: this.consoleUrl,
|
|
675
|
+
appId: this.appId,
|
|
676
|
+
javascriptKey: this.javascriptKey,
|
|
677
|
+
fetch: this._fetch
|
|
678
|
+
});
|
|
679
|
+
}
|
|
520
680
|
getSessionToken() {
|
|
521
681
|
return this.sessionToken;
|
|
522
682
|
}
|
|
@@ -537,16 +697,16 @@ var RoxyonClient = class {
|
|
|
537
697
|
},
|
|
538
698
|
body: JSON.stringify({ scope: "public" })
|
|
539
699
|
});
|
|
540
|
-
const
|
|
541
|
-
if (!
|
|
700
|
+
const json2 = await res.json().catch(() => ({}));
|
|
701
|
+
if (!json2.access_token && !json2.session_token) {
|
|
542
702
|
throw new RoxyonApiError("Could not obtain an anonymous BaaS token.", {
|
|
543
703
|
status: res.status,
|
|
544
|
-
body:
|
|
704
|
+
body: json2
|
|
545
705
|
});
|
|
546
706
|
}
|
|
547
|
-
|
|
548
|
-
this.anon =
|
|
549
|
-
return
|
|
707
|
+
json2._expiresAt = Date.now() + (json2.expires_in ? json2.expires_in * 1e3 : 36e5);
|
|
708
|
+
this.anon = json2;
|
|
709
|
+
return json2;
|
|
550
710
|
}
|
|
551
711
|
/** A Personal Access Token (`roxp_…`) authenticates the console endpoints via
|
|
552
712
|
* `Authorization: Bearer`; it is not a BaaS session token. */
|
|
@@ -596,17 +756,17 @@ var RoxyonClient = class {
|
|
|
596
756
|
throw new RoxyonApiError(`Network error calling ${method} ${url}`, { body: cause });
|
|
597
757
|
}
|
|
598
758
|
const text = await res.text();
|
|
599
|
-
let
|
|
759
|
+
let json2;
|
|
600
760
|
try {
|
|
601
|
-
|
|
761
|
+
json2 = text ? JSON.parse(text) : {};
|
|
602
762
|
} catch {
|
|
603
|
-
|
|
763
|
+
json2 = { error: text || `HTTP ${res.status}`, _raw: text };
|
|
604
764
|
}
|
|
605
765
|
if (!res.ok && !opts.tolerateHttpError) {
|
|
606
|
-
const msg =
|
|
607
|
-
throw new RoxyonApiError(String(msg), { status: res.status, body:
|
|
766
|
+
const msg = json2 && typeof json2 === "object" && "error" in json2 && json2.error || `HTTP ${res.status} calling ${method} ${path}`;
|
|
767
|
+
throw new RoxyonApiError(String(msg), { status: res.status, body: json2 });
|
|
608
768
|
}
|
|
609
|
-
return
|
|
769
|
+
return json2;
|
|
610
770
|
}
|
|
611
771
|
get(path, query, opts) {
|
|
612
772
|
return this.request("GET", path, { ...opts, query });
|
|
@@ -622,6 +782,41 @@ var RoxyonClient = class {
|
|
|
622
782
|
}
|
|
623
783
|
};
|
|
624
784
|
|
|
785
|
+
// src/databases.ts
|
|
786
|
+
var DatabasesApi = class {
|
|
787
|
+
constructor(client) {
|
|
788
|
+
this.client = client;
|
|
789
|
+
}
|
|
790
|
+
client;
|
|
791
|
+
async list(subscriptionId) {
|
|
792
|
+
const r = await this.client.get("/Databases", {
|
|
793
|
+
fields: "objectId,Name,Username,Status",
|
|
794
|
+
limit: -1,
|
|
795
|
+
order: "-createdAt",
|
|
796
|
+
where: { Subscription: subscriptionId, eye: { in: "1,0" } }
|
|
797
|
+
});
|
|
798
|
+
return r.results ?? [];
|
|
799
|
+
}
|
|
800
|
+
/** `POST /databases/create` — provision a database + user; the reconciler does the rest. */
|
|
801
|
+
async create(input) {
|
|
802
|
+
const r = await this.client.console("POST", "/databases/create", {
|
|
803
|
+
body: input,
|
|
804
|
+
tolerateHttpError: true
|
|
805
|
+
});
|
|
806
|
+
if (!r?.ok) throw new RoxyonApiError(r?.error || "Could not create the database.", { body: r });
|
|
807
|
+
return r;
|
|
808
|
+
}
|
|
809
|
+
/** `POST /databases/delete` */
|
|
810
|
+
async delete(databaseId) {
|
|
811
|
+
const r = await this.client.console("POST", "/databases/delete", {
|
|
812
|
+
body: { database: databaseId },
|
|
813
|
+
tolerateHttpError: true
|
|
814
|
+
});
|
|
815
|
+
if (!r?.ok) throw new RoxyonApiError(r?.error || "Could not delete the database.", { body: r });
|
|
816
|
+
return r;
|
|
817
|
+
}
|
|
818
|
+
};
|
|
819
|
+
|
|
625
820
|
// src/domains.ts
|
|
626
821
|
var DomainsApi = class {
|
|
627
822
|
constructor(client) {
|
|
@@ -652,6 +847,41 @@ var DomainsApi = class {
|
|
|
652
847
|
}
|
|
653
848
|
};
|
|
654
849
|
|
|
850
|
+
// src/email.ts
|
|
851
|
+
var EmailApi = class {
|
|
852
|
+
constructor(client) {
|
|
853
|
+
this.client = client;
|
|
854
|
+
}
|
|
855
|
+
client;
|
|
856
|
+
async list(subscriptionId) {
|
|
857
|
+
const r = await this.client.get("/Emails", {
|
|
858
|
+
fields: "objectId,Email,LocalPart,Status,Quota",
|
|
859
|
+
limit: -1,
|
|
860
|
+
order: "-createdAt",
|
|
861
|
+
where: { Subscription: subscriptionId, eye: { in: "1,0" } }
|
|
862
|
+
});
|
|
863
|
+
return r.results ?? [];
|
|
864
|
+
}
|
|
865
|
+
/** `POST /emails/create` — provision a mailbox; the reconciler does the rest. */
|
|
866
|
+
async create(input) {
|
|
867
|
+
const r = await this.client.console("POST", "/emails/create", {
|
|
868
|
+
body: input,
|
|
869
|
+
tolerateHttpError: true
|
|
870
|
+
});
|
|
871
|
+
if (!r?.ok) throw new RoxyonApiError(r?.error || "Could not create the mailbox.", { body: r });
|
|
872
|
+
return r;
|
|
873
|
+
}
|
|
874
|
+
/** `POST /emails/delete` */
|
|
875
|
+
async delete(emailId) {
|
|
876
|
+
const r = await this.client.console("POST", "/emails/delete", {
|
|
877
|
+
body: { email: emailId },
|
|
878
|
+
tolerateHttpError: true
|
|
879
|
+
});
|
|
880
|
+
if (!r?.ok) throw new RoxyonApiError(r?.error || "Could not delete the mailbox.", { body: r });
|
|
881
|
+
return r;
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
|
|
655
885
|
// src/sites.ts
|
|
656
886
|
var SitesApi = class {
|
|
657
887
|
constructor(client) {
|
|
@@ -696,6 +926,30 @@ var SitesApi = class {
|
|
|
696
926
|
}
|
|
697
927
|
};
|
|
698
928
|
|
|
929
|
+
// src/ssh.ts
|
|
930
|
+
var SshApi = class {
|
|
931
|
+
constructor(client) {
|
|
932
|
+
this.client = client;
|
|
933
|
+
}
|
|
934
|
+
client;
|
|
935
|
+
/** `POST /ssh/password` */
|
|
936
|
+
async resetPassword(input = {}) {
|
|
937
|
+
const r = await this.client.console("POST", "/ssh/password", {
|
|
938
|
+
body: input,
|
|
939
|
+
tolerateHttpError: true
|
|
940
|
+
});
|
|
941
|
+
if (!r?.ok) {
|
|
942
|
+
throw new RoxyonApiError(
|
|
943
|
+
r?.error || "Could not reset the password.",
|
|
944
|
+
{
|
|
945
|
+
body: r
|
|
946
|
+
}
|
|
947
|
+
);
|
|
948
|
+
}
|
|
949
|
+
return r;
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
|
|
699
953
|
// src/subscriptions.ts
|
|
700
954
|
var SubscriptionsApi = class {
|
|
701
955
|
constructor(client) {
|
|
@@ -795,6 +1049,112 @@ var TokensApi = class {
|
|
|
795
1049
|
}
|
|
796
1050
|
};
|
|
797
1051
|
|
|
1052
|
+
// src/baas-data.ts
|
|
1053
|
+
var DEFAULT_BAAS_V2_URL = "https://www.beaapis.com/2";
|
|
1054
|
+
var BAAS_MAX_PAGE = 200;
|
|
1055
|
+
var BAAS_MAX_BATCH = 50;
|
|
1056
|
+
var CLASS_RE = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
|
|
1057
|
+
var ID_RE = /^[A-Za-z0-9]{1,40}$/;
|
|
1058
|
+
function checkClass(name) {
|
|
1059
|
+
if (!CLASS_RE.test(name)) throw new Error(`Invalid class name "${name}".`);
|
|
1060
|
+
return name;
|
|
1061
|
+
}
|
|
1062
|
+
function checkId(id) {
|
|
1063
|
+
if (!ID_RE.test(id)) throw new Error(`Invalid objectId "${id}".`);
|
|
1064
|
+
return id;
|
|
1065
|
+
}
|
|
1066
|
+
var BaasDataApi = class _BaasDataApi {
|
|
1067
|
+
baseUrl;
|
|
1068
|
+
secretKey;
|
|
1069
|
+
_fetch;
|
|
1070
|
+
constructor(opts) {
|
|
1071
|
+
if (!opts.secretKey.startsWith("rxsk_")) {
|
|
1072
|
+
throw new Error("BaaS V2 needs the app secret key (starts with rxsk_).");
|
|
1073
|
+
}
|
|
1074
|
+
this.secretKey = opts.secretKey;
|
|
1075
|
+
this.baseUrl = (opts.baseUrl ?? DEFAULT_BAAS_V2_URL).replace(/\/+$/, "");
|
|
1076
|
+
this._fetch = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
1077
|
+
}
|
|
1078
|
+
async call(method, path, opts = {}) {
|
|
1079
|
+
const qs = opts.query && Object.keys(opts.query).length ? `?${new URLSearchParams(opts.query)}` : "";
|
|
1080
|
+
const headers = { "x-rx-secret-key": this.secretKey };
|
|
1081
|
+
if (opts.body !== void 0) headers["content-type"] = "application/json";
|
|
1082
|
+
let res;
|
|
1083
|
+
try {
|
|
1084
|
+
res = await this._fetch(`${this.baseUrl}${path}${qs}`, {
|
|
1085
|
+
method,
|
|
1086
|
+
headers,
|
|
1087
|
+
body: opts.body === void 0 ? void 0 : JSON.stringify(opts.body)
|
|
1088
|
+
});
|
|
1089
|
+
} catch (e) {
|
|
1090
|
+
throw new RoxyonApiError(`Could not reach ${this.baseUrl}: ${e.message}`);
|
|
1091
|
+
}
|
|
1092
|
+
let body = {};
|
|
1093
|
+
try {
|
|
1094
|
+
body = await res.json() ?? {};
|
|
1095
|
+
} catch {
|
|
1096
|
+
}
|
|
1097
|
+
if (!res.ok || body.ok !== true) {
|
|
1098
|
+
const msg = body.message || body.error || `HTTP ${res.status}`;
|
|
1099
|
+
throw new RoxyonApiError(msg, { status: res.status, type: body.error, body });
|
|
1100
|
+
}
|
|
1101
|
+
return body;
|
|
1102
|
+
}
|
|
1103
|
+
static recordPath(className, id) {
|
|
1104
|
+
return `/records/${checkClass(className)}${id === void 0 ? "" : `/${checkId(id)}`}`;
|
|
1105
|
+
}
|
|
1106
|
+
async query(className, q = {}) {
|
|
1107
|
+
const limit = q.limit ?? 50;
|
|
1108
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > BAAS_MAX_PAGE) {
|
|
1109
|
+
throw new Error(`limit must be 1 to ${BAAS_MAX_PAGE}.`);
|
|
1110
|
+
}
|
|
1111
|
+
const query = { fields: q.fields || "*", limit: String(limit) };
|
|
1112
|
+
if (q.where && Object.keys(q.where).length) query.where = JSON.stringify(q.where);
|
|
1113
|
+
if (q.order) query.order = q.order;
|
|
1114
|
+
if (q.skip) query.skip = String(q.skip);
|
|
1115
|
+
if (q.count) query.count = "1";
|
|
1116
|
+
const r = await this.call("GET", _BaasDataApi.recordPath(className), { query });
|
|
1117
|
+
return {
|
|
1118
|
+
rows: r.results ?? [],
|
|
1119
|
+
...r.count !== void 0 ? { count: r.count } : {}
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
async get(className, objectId) {
|
|
1123
|
+
const r = await this.call("GET", _BaasDataApi.recordPath(className, objectId));
|
|
1124
|
+
return r.result ?? {};
|
|
1125
|
+
}
|
|
1126
|
+
/** Returns the created row as stored. */
|
|
1127
|
+
async create(className, data) {
|
|
1128
|
+
const r = await this.call("POST", _BaasDataApi.recordPath(className), { body: { data } });
|
|
1129
|
+
return r.result ?? {};
|
|
1130
|
+
}
|
|
1131
|
+
async update(className, objectId, data) {
|
|
1132
|
+
const r = await this.call("PUT", _BaasDataApi.recordPath(className, objectId), {
|
|
1133
|
+
body: { data }
|
|
1134
|
+
});
|
|
1135
|
+
return r.result ?? {};
|
|
1136
|
+
}
|
|
1137
|
+
/** The id goes in the URL path, never the body. */
|
|
1138
|
+
async delete(className, objectId) {
|
|
1139
|
+
await this.call("DELETE", _BaasDataApi.recordPath(className, objectId));
|
|
1140
|
+
}
|
|
1141
|
+
/** 1 to 50 record requests in one call; one failing doesn't stop the others. */
|
|
1142
|
+
async batch(requests) {
|
|
1143
|
+
if (requests.length < 1 || requests.length > BAAS_MAX_BATCH) {
|
|
1144
|
+
throw new Error(`A batch takes 1 to ${BAAS_MAX_BATCH} requests.`);
|
|
1145
|
+
}
|
|
1146
|
+
for (const req of requests) {
|
|
1147
|
+
const [cls, id, extra] = req.path.split("/").filter(Boolean);
|
|
1148
|
+
if (!cls || extra !== void 0)
|
|
1149
|
+
throw new Error(`Batch path "${req.path}" must be /Class or /Class/id.`);
|
|
1150
|
+
checkClass(cls);
|
|
1151
|
+
if (id !== void 0) checkId(id);
|
|
1152
|
+
}
|
|
1153
|
+
const r = await this.call("POST", "/batch", { body: { requests } });
|
|
1154
|
+
return r.results ?? [];
|
|
1155
|
+
}
|
|
1156
|
+
};
|
|
1157
|
+
|
|
798
1158
|
// src/env.ts
|
|
799
1159
|
function parseEnv(text) {
|
|
800
1160
|
const out = {};
|
|
@@ -871,6 +1231,10 @@ var Roxyon = class {
|
|
|
871
1231
|
domains;
|
|
872
1232
|
applications;
|
|
873
1233
|
sites;
|
|
1234
|
+
databases;
|
|
1235
|
+
email;
|
|
1236
|
+
ssh;
|
|
1237
|
+
billing;
|
|
874
1238
|
constructor(options = {}) {
|
|
875
1239
|
this.client = options instanceof RoxyonClient ? options : new RoxyonClient(options);
|
|
876
1240
|
this.auth = new AuthApi(this.client);
|
|
@@ -880,6 +1244,10 @@ var Roxyon = class {
|
|
|
880
1244
|
this.domains = new DomainsApi(this.client);
|
|
881
1245
|
this.applications = new ApplicationsApi(this.client);
|
|
882
1246
|
this.sites = new SitesApi(this.client);
|
|
1247
|
+
this.databases = new DatabasesApi(this.client);
|
|
1248
|
+
this.email = new EmailApi(this.client);
|
|
1249
|
+
this.ssh = new SshApi(this.client);
|
|
1250
|
+
this.billing = new BillingApi(this.client);
|
|
883
1251
|
}
|
|
884
1252
|
get sessionToken() {
|
|
885
1253
|
return this.client.getSessionToken();
|
|
@@ -890,22 +1258,33 @@ var Roxyon = class {
|
|
|
890
1258
|
AccountApi,
|
|
891
1259
|
ApplicationsApi,
|
|
892
1260
|
AuthApi,
|
|
1261
|
+
BAAS_MAX_BATCH,
|
|
1262
|
+
BAAS_MAX_PAGE,
|
|
1263
|
+
BILLING_CYCLES,
|
|
1264
|
+
BaasDataApi,
|
|
1265
|
+
BillingApi,
|
|
893
1266
|
DEFAULT_APP,
|
|
894
1267
|
DEFAULT_BAAS_URL,
|
|
1268
|
+
DEFAULT_BAAS_V2_URL,
|
|
895
1269
|
DEFAULT_CONSOLE_URL,
|
|
1270
|
+
DatabasesApi,
|
|
896
1271
|
DomainsApi,
|
|
1272
|
+
EmailApi,
|
|
897
1273
|
LUMEN_BUILD,
|
|
1274
|
+
PAYABLE_STATUSES,
|
|
898
1275
|
RUNTIMES,
|
|
899
1276
|
Roxyon,
|
|
900
1277
|
RoxyonApiError,
|
|
901
1278
|
RoxyonClient,
|
|
902
1279
|
SitesApi,
|
|
1280
|
+
SshApi,
|
|
903
1281
|
SubscriptionsApi,
|
|
904
1282
|
TokensApi,
|
|
905
1283
|
assertOk,
|
|
906
1284
|
envFromStored,
|
|
907
1285
|
formatEnv,
|
|
908
1286
|
isAuthError,
|
|
1287
|
+
isPayable,
|
|
909
1288
|
parseEnv,
|
|
910
1289
|
rxError,
|
|
911
1290
|
toQueryString
|