vibecash 0.2.1 → 0.2.3
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.js +86 -45
- package/package.json +23 -7
package/dist/index.js
CHANGED
|
@@ -165,7 +165,11 @@ function registerWalletCommands(program2) {
|
|
|
165
165
|
try {
|
|
166
166
|
const data = await apiRequest("POST", "/wallets/current/claim_link");
|
|
167
167
|
output(data, (d) => {
|
|
168
|
-
return
|
|
168
|
+
return [
|
|
169
|
+
`Claim URL: ${d.claimUrl || "N/A"}`,
|
|
170
|
+
`Claim Token: ${d.claimToken || "N/A"}`,
|
|
171
|
+
`Expires At: ${d.expiresAt ? fmtDate(d.expiresAt) : "N/A"}`
|
|
172
|
+
].join("\n");
|
|
169
173
|
});
|
|
170
174
|
} catch (err) {
|
|
171
175
|
console.error(`Error: ${err.message}`);
|
|
@@ -296,22 +300,31 @@ function registerPriceCommands(program2) {
|
|
|
296
300
|
// src/commands/checkout.ts
|
|
297
301
|
function registerCheckoutCommands(program2) {
|
|
298
302
|
const checkout = program2.command("checkout").description("Manage checkout sessions");
|
|
299
|
-
checkout.command("create").description("Create a new checkout session").requiredOption("-p, --price-id <priceId>", "Price ID to checkout").requiredOption("--success-url <url>", "URL to redirect on success").requiredOption("--cancel-url <url>", "URL to redirect on cancel").option("-m, --mode <mode>", "payment or subscription", "payment").option("-q, --quantity <quantity>", "Quantity", "1").option("--methods <methods>", "Payment methods (comma-separated: card,alipay,paynow,wechat)", "card,alipay,paynow,wechat").action(async (opts) => {
|
|
303
|
+
checkout.command("create").description("Create a new checkout session").requiredOption("-p, --price-id <priceId>", "Price ID to checkout").requiredOption("--success-url <url>", "URL to redirect on success").requiredOption("--cancel-url <url>", "URL to redirect on cancel").option("-m, --mode <mode>", "payment or subscription", "payment").option("-q, --quantity <quantity>", "Quantity", "1").option("--methods <methods>", "Payment methods (comma-separated: card,alipay,paynow,wechat)", "card,alipay,paynow,wechat").option("--customer-id <id>", "Customer ID (optional, auto-created from email at payment time)").option("--trial-days <days>", "Trial period in days (subscription mode)").action(async (opts) => {
|
|
300
304
|
try {
|
|
301
305
|
const body = {
|
|
302
306
|
mode: opts.mode,
|
|
303
307
|
lineItems: [{ priceId: opts.priceId, quantity: parseInt(opts.quantity, 10) }],
|
|
304
308
|
successUrl: opts.successUrl,
|
|
305
|
-
cancelUrl: opts.cancelUrl
|
|
306
|
-
paymentMethodTypes: opts.methods.split(",").map((m) => m.trim())
|
|
309
|
+
cancelUrl: opts.cancelUrl
|
|
307
310
|
};
|
|
311
|
+
if (opts.mode === "subscription") {
|
|
312
|
+
body.paymentMethodTypes = ["card"];
|
|
313
|
+
} else {
|
|
314
|
+
body.paymentMethodTypes = opts.methods.split(",").map((m) => m.trim());
|
|
315
|
+
}
|
|
316
|
+
if (opts.customerId) body.customerId = opts.customerId;
|
|
317
|
+
if (opts.trialDays) body.trialPeriodDays = parseInt(opts.trialDays, 10);
|
|
308
318
|
const data = await apiRequest("POST", "/checkout/sessions", body);
|
|
309
319
|
success("Checkout session created");
|
|
310
320
|
output(data, (d) => {
|
|
311
|
-
|
|
321
|
+
const lines = [
|
|
312
322
|
`Session ID: ${d.id}`,
|
|
323
|
+
`Mode: ${d.mode}`,
|
|
313
324
|
`Checkout URL: ${d.url || d.checkoutUrl || "N/A"}`
|
|
314
|
-
]
|
|
325
|
+
];
|
|
326
|
+
if (d.mode === "subscription") lines.push(`(Subscription \u2014 customer will be created from email at checkout)`);
|
|
327
|
+
return lines.join("\n");
|
|
315
328
|
});
|
|
316
329
|
} catch (err) {
|
|
317
330
|
console.error(`Error: ${err.message}`);
|
|
@@ -394,18 +407,27 @@ function registerSubscriptionCommands(program2) {
|
|
|
394
407
|
process.exit(1);
|
|
395
408
|
}
|
|
396
409
|
});
|
|
397
|
-
subscription.command("cancel <id>").description("Cancel a subscription").action(async (id) => {
|
|
410
|
+
subscription.command("cancel <id>").description("Cancel a subscription immediately").action(async (id) => {
|
|
398
411
|
try {
|
|
399
|
-
await apiRequest("
|
|
412
|
+
await apiRequest("DELETE", `/subscriptions/${id}`);
|
|
400
413
|
success(`Subscription ${id} cancelled`);
|
|
401
414
|
} catch (err) {
|
|
402
415
|
console.error(`Error: ${err.message}`);
|
|
403
416
|
process.exit(1);
|
|
404
417
|
}
|
|
405
418
|
});
|
|
406
|
-
subscription.command("
|
|
419
|
+
subscription.command("pause <id>").description("Set subscription to cancel at end of current period").action(async (id) => {
|
|
407
420
|
try {
|
|
408
|
-
await apiRequest("
|
|
421
|
+
await apiRequest("PATCH", `/subscriptions/${id}`, { cancelAtPeriodEnd: true });
|
|
422
|
+
success(`Subscription ${id} will cancel at period end`);
|
|
423
|
+
} catch (err) {
|
|
424
|
+
console.error(`Error: ${err.message}`);
|
|
425
|
+
process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
subscription.command("resume <id>").description("Resume a subscription set to cancel at period end").action(async (id) => {
|
|
429
|
+
try {
|
|
430
|
+
await apiRequest("PATCH", `/subscriptions/${id}`, { cancelAtPeriodEnd: false });
|
|
409
431
|
success(`Subscription ${id} resumed`);
|
|
410
432
|
} catch (err) {
|
|
411
433
|
console.error(`Error: ${err.message}`);
|
|
@@ -464,11 +486,31 @@ function registerCustomerCommands(program2) {
|
|
|
464
486
|
process.exit(1);
|
|
465
487
|
}
|
|
466
488
|
});
|
|
467
|
-
customer.command("
|
|
489
|
+
customer.command("delete <id>").description("Delete a customer").action(async (id) => {
|
|
468
490
|
try {
|
|
469
|
-
|
|
470
|
-
success(
|
|
471
|
-
|
|
491
|
+
await apiRequest("DELETE", `/customers/${id}`);
|
|
492
|
+
success(`Customer ${id} deleted`);
|
|
493
|
+
} catch (err) {
|
|
494
|
+
console.error(`Error: ${err.message}`);
|
|
495
|
+
process.exit(1);
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
customer.command("update <id>").description("Update a customer").option("-e, --email <email>", "New email").option("-n, --name <name>", "New name").action(async (id, opts) => {
|
|
499
|
+
try {
|
|
500
|
+
const body = {};
|
|
501
|
+
if (opts.email) body.email = opts.email;
|
|
502
|
+
if (opts.name) body.name = opts.name;
|
|
503
|
+
if (Object.keys(body).length === 0) {
|
|
504
|
+
console.error("Provide at least --email or --name to update.");
|
|
505
|
+
process.exit(1);
|
|
506
|
+
}
|
|
507
|
+
const data = await apiRequest("PATCH", `/customers/${id}`, body);
|
|
508
|
+
success("Customer updated");
|
|
509
|
+
output(data, (d) => [
|
|
510
|
+
`Customer ID: ${d.id}`,
|
|
511
|
+
`Email: ${d.email}`,
|
|
512
|
+
`Name: ${d.name || "N/A"}`
|
|
513
|
+
].join("\n"));
|
|
472
514
|
} catch (err) {
|
|
473
515
|
console.error(`Error: ${err.message}`);
|
|
474
516
|
process.exit(1);
|
|
@@ -586,8 +628,8 @@ function registerCreateCommand(program2) {
|
|
|
586
628
|
process.exit(1);
|
|
587
629
|
}
|
|
588
630
|
const amountStr = await prompt("Amount (in smallest currency unit, e.g. 1000 for $10.00): ");
|
|
589
|
-
const
|
|
590
|
-
if (isNaN(
|
|
631
|
+
const unitAmount = parseInt(amountStr, 10);
|
|
632
|
+
if (isNaN(unitAmount) || unitAmount <= 0) {
|
|
591
633
|
console.error("Invalid amount.");
|
|
592
634
|
process.exit(1);
|
|
593
635
|
}
|
|
@@ -613,7 +655,7 @@ function registerCreateCommand(program2) {
|
|
|
613
655
|
console.log("Creating price...");
|
|
614
656
|
const priceBody = {
|
|
615
657
|
productId: product.id,
|
|
616
|
-
|
|
658
|
+
unitAmount,
|
|
617
659
|
type,
|
|
618
660
|
currency
|
|
619
661
|
};
|
|
@@ -621,8 +663,10 @@ function registerCreateCommand(program2) {
|
|
|
621
663
|
const price = await apiRequest("POST", "/prices", priceBody);
|
|
622
664
|
success(`Price created: ${price.id}`);
|
|
623
665
|
console.log("Creating checkout session...");
|
|
666
|
+
const mode = type === "recurring" ? "subscription" : "payment";
|
|
624
667
|
const session = await apiRequest("POST", "/checkout/sessions", {
|
|
625
|
-
|
|
668
|
+
mode,
|
|
669
|
+
lineItems: [{ priceId: price.id, quantity: 1 }],
|
|
626
670
|
successUrl,
|
|
627
671
|
cancelUrl
|
|
628
672
|
});
|
|
@@ -634,7 +678,7 @@ Checkout URL: ${checkoutUrl}`);
|
|
|
634
678
|
}
|
|
635
679
|
output({
|
|
636
680
|
product: { id: product.id, name: productName },
|
|
637
|
-
price: { id: price.id,
|
|
681
|
+
price: { id: price.id, unitAmount, currency, type, interval },
|
|
638
682
|
checkout: { id: session.id, url: checkoutUrl }
|
|
639
683
|
});
|
|
640
684
|
} catch (err) {
|
|
@@ -721,7 +765,7 @@ function registerBankCommands(program2) {
|
|
|
721
765
|
const bank = program2.command("bank").description("Manage bank accounts");
|
|
722
766
|
bank.command("list").description("List all bank accounts").action(async () => {
|
|
723
767
|
try {
|
|
724
|
-
const data = await apiRequest("GET", "/
|
|
768
|
+
const data = await apiRequest("GET", "/bank_accounts");
|
|
725
769
|
output(data, (d) => {
|
|
726
770
|
const items = d.data || d.bankAccounts || d;
|
|
727
771
|
if (!Array.isArray(items) || items.length === 0) return "No bank accounts found.";
|
|
@@ -744,19 +788,19 @@ function registerBankCommands(program2) {
|
|
|
744
788
|
});
|
|
745
789
|
bank.command("add").description("Add a new bank account").action(async () => {
|
|
746
790
|
try {
|
|
747
|
-
const
|
|
791
|
+
const accountName = await prompt2("Account holder name: ");
|
|
748
792
|
const bankName = await prompt2("Bank name: ");
|
|
749
|
-
const
|
|
793
|
+
const bankCode = await prompt2("Bank code / routing number (press Enter to skip): ");
|
|
750
794
|
const accountNumber = await prompt2("Account number: ");
|
|
751
|
-
const
|
|
795
|
+
const currency = await prompt2("Currency (default: SGD): ") || "SGD";
|
|
752
796
|
const body = {
|
|
753
|
-
|
|
797
|
+
accountName,
|
|
754
798
|
bankName,
|
|
755
|
-
routingNumber,
|
|
756
799
|
accountNumber,
|
|
757
|
-
|
|
800
|
+
currency
|
|
758
801
|
};
|
|
759
|
-
|
|
802
|
+
if (bankCode) body.bankCode = bankCode;
|
|
803
|
+
const data = await apiRequest("POST", "/bank_accounts", body);
|
|
760
804
|
success("Bank account added");
|
|
761
805
|
output(data, (d) => [
|
|
762
806
|
`Bank Account ID: ${d.id}`,
|
|
@@ -770,7 +814,7 @@ function registerBankCommands(program2) {
|
|
|
770
814
|
});
|
|
771
815
|
bank.command("remove <id>").description("Remove a bank account").action(async (id) => {
|
|
772
816
|
try {
|
|
773
|
-
await apiRequest("DELETE", `/
|
|
817
|
+
await apiRequest("DELETE", `/bank_accounts/${id}`);
|
|
774
818
|
success(`Bank account ${id} removed`);
|
|
775
819
|
} catch (err) {
|
|
776
820
|
console.error(`Error: ${err.message}`);
|
|
@@ -779,7 +823,7 @@ function registerBankCommands(program2) {
|
|
|
779
823
|
});
|
|
780
824
|
bank.command("set-default <id>").description("Set a bank account as default").action(async (id) => {
|
|
781
825
|
try {
|
|
782
|
-
await apiRequest("PATCH", `/
|
|
826
|
+
await apiRequest("PATCH", `/bank_accounts/${id}`, { isDefault: true });
|
|
783
827
|
success(`Bank account ${id} set as default`);
|
|
784
828
|
} catch (err) {
|
|
785
829
|
console.error(`Error: ${err.message}`);
|
|
@@ -805,22 +849,20 @@ function registerKycCommands(program2) {
|
|
|
805
849
|
try {
|
|
806
850
|
const fullName = await prompt3("Full name: ");
|
|
807
851
|
const dateOfBirth = await prompt3("Date of birth (YYYY-MM-DD): ");
|
|
808
|
-
const
|
|
809
|
-
const
|
|
810
|
-
const
|
|
811
|
-
const
|
|
812
|
-
const
|
|
852
|
+
const nationality = await prompt3("Nationality (2-letter code, e.g. SG): ");
|
|
853
|
+
const documentType = await prompt3("Document type (passport / national_id / drivers_license): ");
|
|
854
|
+
const documentNumber = await prompt3("Document number: ");
|
|
855
|
+
const documentFrontUrl = await prompt3("Document front image URL: ");
|
|
856
|
+
const documentBackUrl = await prompt3("Document back image URL (press Enter to skip): ");
|
|
813
857
|
const body = {
|
|
814
858
|
fullName,
|
|
815
859
|
dateOfBirth,
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
postalCode,
|
|
821
|
-
country
|
|
822
|
-
}
|
|
860
|
+
nationality,
|
|
861
|
+
documentType,
|
|
862
|
+
documentNumber,
|
|
863
|
+
documentFrontUrl
|
|
823
864
|
};
|
|
865
|
+
if (documentBackUrl) body.documentBackUrl = documentBackUrl;
|
|
824
866
|
const data = await apiRequest("POST", "/kyc", body);
|
|
825
867
|
success("KYC submission received");
|
|
826
868
|
output(data, (d) => {
|
|
@@ -839,9 +881,8 @@ function registerKycCommands(program2) {
|
|
|
839
881
|
const data = await apiRequest("GET", "/kyc/status");
|
|
840
882
|
output(data, (d) => {
|
|
841
883
|
return [
|
|
842
|
-
`
|
|
843
|
-
`
|
|
844
|
-
`Requirements: ${d.requirements ? JSON.stringify(d.requirements) : "None"}`
|
|
884
|
+
`Account ID: ${d.accountId || "N/A"}`,
|
|
885
|
+
`KYC Status: ${d.kycStatus || "N/A"}`
|
|
845
886
|
].join("\n");
|
|
846
887
|
});
|
|
847
888
|
} catch (err) {
|
|
@@ -949,7 +990,7 @@ function registerWebhookCommands(program2) {
|
|
|
949
990
|
|
|
950
991
|
// src/index.ts
|
|
951
992
|
var program = new Command();
|
|
952
|
-
program.name("vibecash").description("VibeCash CLI - manage payments from the command line").version("0.2.
|
|
993
|
+
program.name("vibecash").description("VibeCash CLI - manage payments from the command line").version("0.2.2").option("--json", "Output in JSON format").hook("preAction", (thisCommand) => {
|
|
953
994
|
const opts = thisCommand.opts();
|
|
954
995
|
if (opts.json) setOutputFormat("json");
|
|
955
996
|
});
|
package/package.json
CHANGED
|
@@ -1,15 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibecash",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "VibeCash CLI - Payment infrastructure for the AI era. Accept cards, e-wallets, and QR payments in Southeast Asia.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
"bin": {
|
|
7
|
+
"vibecash": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsup",
|
|
14
|
+
"dev": "tsx src/index.ts"
|
|
15
|
+
},
|
|
9
16
|
"keywords": [
|
|
10
|
-
"payment",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
17
|
+
"payment",
|
|
18
|
+
"cli",
|
|
19
|
+
"checkout",
|
|
20
|
+
"subscription",
|
|
21
|
+
"billing",
|
|
22
|
+
"vibecash",
|
|
23
|
+
"ai-native",
|
|
24
|
+
"southeast-asia",
|
|
25
|
+
"singapore",
|
|
26
|
+
"wechat-pay",
|
|
27
|
+
"alipay",
|
|
28
|
+
"paynow"
|
|
13
29
|
],
|
|
14
30
|
"author": "VibeCash",
|
|
15
31
|
"license": "MIT",
|