terminalmarket 0.13.2 → 0.14.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/bin/tm.js +222 -125
- package/package.json +1 -1
- package/src/format.js +20 -0
package/bin/tm.js
CHANGED
|
@@ -26,6 +26,18 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
26
26
|
const __dirname = dirname(__filename);
|
|
27
27
|
const pkg = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
|
|
28
28
|
const VERSION = pkg.version;
|
|
29
|
+
const commandManifest = (() => {
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(
|
|
32
|
+
readFileSync(
|
|
33
|
+
join(__dirname, "../../../shared/command-manifest.json"),
|
|
34
|
+
"utf-8",
|
|
35
|
+
),
|
|
36
|
+
);
|
|
37
|
+
} catch {
|
|
38
|
+
return { cli: { quickStart: [], groups: [] } };
|
|
39
|
+
}
|
|
40
|
+
})();
|
|
29
41
|
|
|
30
42
|
function getPublicBaseUrl() {
|
|
31
43
|
const apiBase = getApiBase();
|
|
@@ -475,8 +487,10 @@ async function showProfile() {
|
|
|
475
487
|
}
|
|
476
488
|
|
|
477
489
|
console.log(chalk.dim(' Use: tm profile set <field> <value>'));
|
|
478
|
-
console.log(chalk.dim(' Fields: name, phone, city, country, github, linkedin, skills, bio, available'));
|
|
490
|
+
console.log(chalk.dim(' Fields: name, email, phone, city, country, github, linkedin, skills, bio, available'));
|
|
479
491
|
console.log(chalk.dim(' telegram, whatsapp, viber, discord, teams, contact'));
|
|
492
|
+
console.log(chalk.dim(' Verify email: tm profile verify email [code]'));
|
|
493
|
+
console.log(chalk.dim(' Verify phone: tm profile verify phone [code]'));
|
|
480
494
|
console.log();
|
|
481
495
|
}
|
|
482
496
|
|
|
@@ -490,6 +504,7 @@ async function setProfileField(field, value) {
|
|
|
490
504
|
// Map CLI field names to API field names
|
|
491
505
|
const fieldMapping = {
|
|
492
506
|
name: "name",
|
|
507
|
+
email: "email",
|
|
493
508
|
phone: "phone",
|
|
494
509
|
address: "address",
|
|
495
510
|
city: "city",
|
|
@@ -530,6 +545,28 @@ async function setProfileField(field, value) {
|
|
|
530
545
|
|
|
531
546
|
await apiPatch("/profile", { [apiField]: processedValue });
|
|
532
547
|
console.log(chalk.green(`✓ Updated ${field} to "${newValue}"`));
|
|
548
|
+
if (field === "email") {
|
|
549
|
+
console.log(chalk.dim(" A verification code was sent to your new email."));
|
|
550
|
+
console.log(chalk.dim(" Confirm with: tm profile verify email <code>"));
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
async function verifyProfileChannel(channel, code) {
|
|
555
|
+
const normalized = String(channel || "").trim().toLowerCase();
|
|
556
|
+
if (!["email", "phone"].includes(normalized)) {
|
|
557
|
+
console.error(chalk.red("✗ Invalid channel. Use: email or phone"));
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
if (!code) {
|
|
562
|
+
await apiPost(`/verification/send-${normalized}`, {});
|
|
563
|
+
console.log(chalk.green(`✓ Verification code sent for ${normalized}.`));
|
|
564
|
+
console.log(chalk.dim(` Confirm with: tm profile verify ${normalized} <code>`));
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
await apiPost(`/verification/verify-${normalized}`, { code: String(code).trim() });
|
|
569
|
+
console.log(chalk.green(`✓ ${normalized[0].toUpperCase() + normalized.slice(1)} verified.`));
|
|
533
570
|
}
|
|
534
571
|
|
|
535
572
|
profile
|
|
@@ -546,7 +583,7 @@ profile
|
|
|
546
583
|
|
|
547
584
|
profile
|
|
548
585
|
.command("set <field> [value...]")
|
|
549
|
-
.description("Update profile field (name, phone, address, city, country)")
|
|
586
|
+
.description("Update profile field (name, email, phone, address, city, country)")
|
|
550
587
|
.action(async (field, value) => {
|
|
551
588
|
try {
|
|
552
589
|
await setProfileField(field, value);
|
|
@@ -556,6 +593,18 @@ profile
|
|
|
556
593
|
}
|
|
557
594
|
});
|
|
558
595
|
|
|
596
|
+
profile
|
|
597
|
+
.command("verify <channel> [code]")
|
|
598
|
+
.description("Send or confirm verification code (email|phone)")
|
|
599
|
+
.action(async (channel, code) => {
|
|
600
|
+
try {
|
|
601
|
+
await verifyProfileChannel(channel, code);
|
|
602
|
+
} catch (e) {
|
|
603
|
+
console.error(chalk.red(e?.message || String(e)));
|
|
604
|
+
process.exitCode = 1;
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
|
|
559
608
|
profile.action(async () => {
|
|
560
609
|
try {
|
|
561
610
|
await showProfile();
|
|
@@ -664,34 +713,146 @@ program
|
|
|
664
713
|
// -----------------
|
|
665
714
|
program
|
|
666
715
|
.command("checkout")
|
|
667
|
-
.description("
|
|
668
|
-
.
|
|
716
|
+
.description("Create order from cart")
|
|
717
|
+
.option("--pickup", "Pick up at store")
|
|
718
|
+
.option("--delivery", "Delivery to address")
|
|
719
|
+
.option("--shipping", "Shipping (post/courier)")
|
|
720
|
+
.option("--phone <phone>", "Contact phone number")
|
|
721
|
+
.option("--address <address>", "Delivery/shipping address")
|
|
722
|
+
.option("-y, --yes", "Skip confirmation prompt")
|
|
723
|
+
.action(async (opts) => {
|
|
669
724
|
try {
|
|
670
725
|
const cartData = await apiGet("/cart");
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
726
|
+
const items = cartData.items || [];
|
|
727
|
+
|
|
728
|
+
if (items.length === 0) {
|
|
729
|
+
console.log(chalk.yellow("Your cart is empty. Add items first with: tm add <product-id>"));
|
|
674
730
|
return;
|
|
675
731
|
}
|
|
676
|
-
|
|
677
|
-
console.log(chalk.bold("Checkout"));
|
|
678
|
-
console.log("");
|
|
679
|
-
console.log("Your items:");
|
|
680
|
-
|
|
732
|
+
|
|
681
733
|
let total = 0;
|
|
682
|
-
|
|
734
|
+
console.log();
|
|
735
|
+
console.log(chalk.bold(" ═══ Checkout ═══"));
|
|
736
|
+
console.log();
|
|
737
|
+
items.forEach((item, i) => {
|
|
683
738
|
const name = item.name || item.product?.name || `Product #${item.productId}`;
|
|
684
739
|
const price = parseFloat(item.price ?? item.product?.price ?? 0);
|
|
685
|
-
const
|
|
740
|
+
const qty = item.quantity || 1;
|
|
741
|
+
const subtotal = price * qty;
|
|
686
742
|
total += subtotal;
|
|
687
|
-
console.log(` ${i + 1}. ${name} x${
|
|
743
|
+
console.log(` ${i + 1}. ${name} x${qty} = $${subtotal.toFixed(2)}`);
|
|
688
744
|
});
|
|
689
|
-
|
|
690
|
-
console.log(
|
|
691
|
-
console.log(
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
745
|
+
console.log();
|
|
746
|
+
console.log(chalk.bold(` Total: $${total.toFixed(2)}`));
|
|
747
|
+
console.log();
|
|
748
|
+
|
|
749
|
+
const hasDigitalOnly = items.length > 0 && items.every(it => {
|
|
750
|
+
const k = it.product?.productKind || it.productKind;
|
|
751
|
+
return k === "digital" || k === "saas";
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
let deliveryMethod = null;
|
|
755
|
+
if (opts.pickup) deliveryMethod = "pickup";
|
|
756
|
+
else if (opts.delivery) deliveryMethod = "delivery";
|
|
757
|
+
else if (opts.shipping) deliveryMethod = "shipping";
|
|
758
|
+
|
|
759
|
+
let phone = opts.phone || null;
|
|
760
|
+
let address = opts.address || null;
|
|
761
|
+
|
|
762
|
+
if (!hasDigitalOnly) {
|
|
763
|
+
// Try to pull phone/address from profile if not provided
|
|
764
|
+
if (!phone || !address) {
|
|
765
|
+
try {
|
|
766
|
+
const profile = await apiGet("/profile");
|
|
767
|
+
if (!phone && profile.phone) phone = profile.phone;
|
|
768
|
+
if (!address) {
|
|
769
|
+
const parts = [profile.address, profile.city, profile.country].filter(Boolean);
|
|
770
|
+
if (parts.length > 0) address = parts.join(", ");
|
|
771
|
+
}
|
|
772
|
+
} catch { /* ignore */ }
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
const inquirer = await import("inquirer").then(m => m.default);
|
|
776
|
+
|
|
777
|
+
// Ask delivery method interactively if not set
|
|
778
|
+
if (!deliveryMethod) {
|
|
779
|
+
const { method } = await inquirer.prompt([{
|
|
780
|
+
type: "list",
|
|
781
|
+
name: "method",
|
|
782
|
+
message: "Delivery method:",
|
|
783
|
+
choices: [
|
|
784
|
+
{ name: "🏪 Pick up at store", value: "pickup" },
|
|
785
|
+
{ name: "🚗 Delivery to address", value: "delivery" },
|
|
786
|
+
{ name: "📦 Shipping (post/courier)", value: "shipping" },
|
|
787
|
+
],
|
|
788
|
+
}]);
|
|
789
|
+
deliveryMethod = method;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// Ask phone if missing
|
|
793
|
+
if (!phone) {
|
|
794
|
+
const { inputPhone } = await inquirer.prompt([{
|
|
795
|
+
type: "input",
|
|
796
|
+
name: "inputPhone",
|
|
797
|
+
message: "Contact phone:",
|
|
798
|
+
validate: v => v.trim().length > 0 || "Phone is required",
|
|
799
|
+
}]);
|
|
800
|
+
phone = inputPhone.trim();
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// Ask address if delivery/shipping and missing
|
|
804
|
+
if ((deliveryMethod === "delivery" || deliveryMethod === "shipping") && !address) {
|
|
805
|
+
const { inputAddress } = await inquirer.prompt([{
|
|
806
|
+
type: "input",
|
|
807
|
+
name: "inputAddress",
|
|
808
|
+
message: "Delivery address:",
|
|
809
|
+
validate: v => v.trim().length > 0 || "Address is required for delivery/shipping",
|
|
810
|
+
}]);
|
|
811
|
+
address = inputAddress.trim();
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
// Confirmation
|
|
816
|
+
if (!opts.yes) {
|
|
817
|
+
const inquirer = await import("inquirer").then(m => m.default);
|
|
818
|
+
console.log();
|
|
819
|
+
if (deliveryMethod) console.log(chalk.dim(` Method: ${deliveryMethod}`));
|
|
820
|
+
if (phone) console.log(chalk.dim(` Phone: ${phone}`));
|
|
821
|
+
if (address) console.log(chalk.dim(` Address: ${address}`));
|
|
822
|
+
console.log();
|
|
823
|
+
const { confirm } = await inquirer.prompt([{
|
|
824
|
+
type: "confirm",
|
|
825
|
+
name: "confirm",
|
|
826
|
+
message: `Place order for $${total.toFixed(2)}?`,
|
|
827
|
+
default: true,
|
|
828
|
+
}]);
|
|
829
|
+
if (!confirm) {
|
|
830
|
+
console.log(chalk.yellow("Order cancelled."));
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// Create order via API
|
|
836
|
+
const orderPayload = {};
|
|
837
|
+
if (deliveryMethod) orderPayload.deliveryMethod = deliveryMethod;
|
|
838
|
+
if (phone) orderPayload.phone = phone;
|
|
839
|
+
if (address) orderPayload.shippingAddress = address;
|
|
840
|
+
|
|
841
|
+
const result = await apiPost("/orders", orderPayload);
|
|
842
|
+
|
|
843
|
+
console.log();
|
|
844
|
+
console.log(chalk.green.bold(" ✓ Order created!"));
|
|
845
|
+
const orderId = result.order?.id || result.id;
|
|
846
|
+
const orderNum = result.order?.orderNumber || result.orderNumber;
|
|
847
|
+
if (orderNum) console.log(` Order: ${chalk.bold(orderNum)}`);
|
|
848
|
+
else if (orderId) console.log(` Order ID: ${chalk.bold(orderId)}`);
|
|
849
|
+
console.log(` Total: $${total.toFixed(2)}`);
|
|
850
|
+
if (deliveryMethod) console.log(` Delivery: ${deliveryMethod}`);
|
|
851
|
+
if (phone) console.log(` Phone: ${phone}`);
|
|
852
|
+
if (address) console.log(` Address: ${address}`);
|
|
853
|
+
console.log();
|
|
854
|
+
console.log(chalk.dim(" View your orders: tm orders"));
|
|
855
|
+
console.log();
|
|
695
856
|
} catch (e) {
|
|
696
857
|
console.error(chalk.red(e?.message || String(e)));
|
|
697
858
|
process.exitCode = 1;
|
|
@@ -2854,39 +3015,13 @@ program
|
|
|
2854
3015
|
// help
|
|
2855
3016
|
// -----------------
|
|
2856
3017
|
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
'Automation': ['watch', 'telegram'],
|
|
2865
|
-
'Developer Jobs': ['jobs', 'job', 'apply', 'applications'],
|
|
2866
|
-
'Stores': ['sellers', 'store', 'reviews', 'where'],
|
|
2867
|
-
'AI Services': ['ai', 'credits', 'topup'],
|
|
2868
|
-
'On-Demand Tasks': ['tasks', 'task'],
|
|
2869
|
-
'Personalization': ['alias', 'reward'],
|
|
2870
|
-
'Integrations': ['apps'],
|
|
2871
|
-
'Info': ['about', 'stats', 'policy', 'privacy', 'faq', 'contact'],
|
|
2872
|
-
'System': ['start', 'doctor', 'config', 'help']
|
|
2873
|
-
};
|
|
2874
|
-
|
|
2875
|
-
// Command groups by level
|
|
2876
|
-
const basicGroups = {
|
|
2877
|
-
'Get Started': ['start', 'where', 'doctor'],
|
|
2878
|
-
'Shop': ['featured', 'deals', 'products', 'search', 'buy', 'book', 'view', 'open'],
|
|
2879
|
-
'Account': ['login', 'register', 'whoami', 'profile']
|
|
2880
|
-
};
|
|
2881
|
-
|
|
2882
|
-
const advancedGroups = {
|
|
2883
|
-
'Cart & Orders': ['cart', 'add', 'checkout', 'orders'],
|
|
2884
|
-
'Reverse Marketplace': ['request'],
|
|
2885
|
-
'Dev Bounties': ['live', 'need', 'ping', 'bounty', 'reputation'],
|
|
2886
|
-
'AI Services': ['ai', 'credits', 'topup'],
|
|
2887
|
-
'Stores': ['sellers', 'store', 'reviews'],
|
|
2888
|
-
'Automation': ['watch', 'telegram', 'alias', 'reward', 'subscribe', 'wishlist', 'webhook']
|
|
2889
|
-
};
|
|
3018
|
+
const cliHelpManifest = commandManifest?.cli || { quickStart: [], groups: [] };
|
|
3019
|
+
|
|
3020
|
+
function baseCommandName(commandSyntax = "") {
|
|
3021
|
+
if (!commandSyntax) return "";
|
|
3022
|
+
const clean = String(commandSyntax).trim().replace(/^tm\s+/, "");
|
|
3023
|
+
return clean.split(/\s+/)[0] || "";
|
|
3024
|
+
}
|
|
2890
3025
|
|
|
2891
3026
|
// Custom help formatter
|
|
2892
3027
|
function showHelp(commandName = null, mode = 'basic') {
|
|
@@ -2949,32 +3084,24 @@ function showHelp(commandName = null, mode = 'basic') {
|
|
|
2949
3084
|
return;
|
|
2950
3085
|
}
|
|
2951
3086
|
|
|
2952
|
-
// Collect
|
|
2953
|
-
const
|
|
2954
|
-
program.commands.forEach(cmd => {
|
|
2955
|
-
const args = (cmd.registeredArguments || []).map(a => a.required ? `<${a.name()}>` : `[${a.name()}]`).join(' ');
|
|
2956
|
-
allCommands[cmd.name()] = {
|
|
2957
|
-
name: cmd.name(),
|
|
2958
|
-
args,
|
|
2959
|
-
desc: cmd.description()
|
|
2960
|
-
};
|
|
2961
|
-
});
|
|
3087
|
+
// Collect declared commands for existence checks
|
|
3088
|
+
const available = new Set(program.commands.map((cmd) => cmd.name()));
|
|
2962
3089
|
|
|
2963
|
-
const COL_WIDTH =
|
|
3090
|
+
const COL_WIDTH = 34;
|
|
2964
3091
|
|
|
2965
|
-
const printGroup = (
|
|
2966
|
-
const groupCmds =
|
|
2967
|
-
.
|
|
2968
|
-
|
|
3092
|
+
const printGroup = (group, color) => {
|
|
3093
|
+
const groupCmds = (group.commands || []).filter((entry) =>
|
|
3094
|
+
available.has(baseCommandName(entry.command)),
|
|
3095
|
+
);
|
|
2969
3096
|
|
|
2970
3097
|
if (groupCmds.length === 0) return;
|
|
2971
3098
|
|
|
2972
|
-
console.log(color.bold(`${icon} ${
|
|
2973
|
-
groupCmds.forEach(
|
|
2974
|
-
const rawCmd =
|
|
2975
|
-
console.log(' ' + chalk.cyan(
|
|
3099
|
+
console.log(color.bold(`${group.icon || '•'} ${group.title}`));
|
|
3100
|
+
groupCmds.forEach((entry) => {
|
|
3101
|
+
const rawCmd = entry.command;
|
|
3102
|
+
console.log(' ' + chalk.cyan(entry.command) +
|
|
2976
3103
|
' '.repeat(Math.max(1, COL_WIDTH - rawCmd.length)) +
|
|
2977
|
-
chalk.dim(
|
|
3104
|
+
chalk.dim(entry.description || ""));
|
|
2978
3105
|
});
|
|
2979
3106
|
console.log();
|
|
2980
3107
|
};
|
|
@@ -2987,17 +3114,17 @@ function showHelp(commandName = null, mode = 'basic') {
|
|
|
2987
3114
|
if (mode === 'basic') {
|
|
2988
3115
|
// Simple, selling help
|
|
2989
3116
|
console.log(chalk.yellow.bold('Quick Start:'));
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
3117
|
+
for (const step of cliHelpManifest.quickStart || []) {
|
|
3118
|
+
const command = step.command || "";
|
|
3119
|
+
console.log(` ${chalk.green(command)}${' '.repeat(Math.max(1, 28 - command.length))}${chalk.dim(step.description || "")}`);
|
|
3120
|
+
}
|
|
2994
3121
|
console.log();
|
|
2995
3122
|
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3123
|
+
for (const group of cliHelpManifest.groups || []) {
|
|
3124
|
+
if (Array.isArray(group.levels) && group.levels.includes("basic")) {
|
|
3125
|
+
printGroup(group, chalk.white);
|
|
3126
|
+
}
|
|
3127
|
+
}
|
|
3001
3128
|
|
|
3002
3129
|
console.log(chalk.dim('─'.repeat(45)));
|
|
3003
3130
|
console.log(chalk.dim(' tm help --advanced') + chalk.dim(' cart, AI, rewards'));
|
|
@@ -3009,12 +3136,11 @@ function showHelp(commandName = null, mode = 'basic') {
|
|
|
3009
3136
|
console.log(chalk.yellow.bold('Advanced Features:'));
|
|
3010
3137
|
console.log();
|
|
3011
3138
|
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
printGroup('Automation', ['watch', 'telegram', 'alias', 'reward', 'subscribe', 'wishlist'], '👁', chalk.cyan);
|
|
3139
|
+
for (const group of cliHelpManifest.groups || []) {
|
|
3140
|
+
if (Array.isArray(group.levels) && group.levels.includes("advanced")) {
|
|
3141
|
+
printGroup(group, chalk.white);
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3018
3144
|
|
|
3019
3145
|
console.log(chalk.dim('─'.repeat(45)));
|
|
3020
3146
|
console.log(chalk.dim(' tm help') + chalk.dim(' basic commands'));
|
|
@@ -3026,42 +3152,10 @@ function showHelp(commandName = null, mode = 'basic') {
|
|
|
3026
3152
|
console.log(chalk.magenta.bold('Usage:'), chalk.green('tm'), chalk.cyan('<command>'), chalk.dim('[options]'));
|
|
3027
3153
|
console.log();
|
|
3028
3154
|
|
|
3029
|
-
const
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
'Reverse Marketplace': chalk.magenta,
|
|
3034
|
-
'Dev Bounties': chalk.red,
|
|
3035
|
-
'Automation': chalk.cyan,
|
|
3036
|
-
'Developer Jobs': chalk.magenta,
|
|
3037
|
-
'Stores': chalk.cyan,
|
|
3038
|
-
'AI Services': chalk.cyan,
|
|
3039
|
-
'On-Demand Tasks': chalk.yellow,
|
|
3040
|
-
'Integrations': chalk.magenta,
|
|
3041
|
-
'Personalization': chalk.white,
|
|
3042
|
-
'Info': chalk.dim,
|
|
3043
|
-
'System': chalk.gray
|
|
3044
|
-
};
|
|
3045
|
-
|
|
3046
|
-
const groupIcons = {
|
|
3047
|
-
'Authentication': '🔐',
|
|
3048
|
-
'Shopping': '🛒',
|
|
3049
|
-
'Cart & Orders': '📦',
|
|
3050
|
-
'Reverse Marketplace': '📋',
|
|
3051
|
-
'Dev Bounties': '🔥',
|
|
3052
|
-
'Automation': '👁',
|
|
3053
|
-
'Developer Jobs': '💼',
|
|
3054
|
-
'Stores': '🏪',
|
|
3055
|
-
'AI Services': '🤖',
|
|
3056
|
-
'On-Demand Tasks': '⚡',
|
|
3057
|
-
'Integrations': '🧩',
|
|
3058
|
-
'Personalization': '⚙️',
|
|
3059
|
-
'Info': 'ℹ️',
|
|
3060
|
-
'System': '💻'
|
|
3061
|
-
};
|
|
3062
|
-
|
|
3063
|
-
for (const [group, cmdNames] of Object.entries(commandGroups)) {
|
|
3064
|
-
printGroup(group, cmdNames, groupIcons[group] || '•', groupColors[group] || chalk.white);
|
|
3155
|
+
for (const group of cliHelpManifest.groups || []) {
|
|
3156
|
+
if (Array.isArray(group.levels) && group.levels.includes("all")) {
|
|
3157
|
+
printGroup(group, chalk.white);
|
|
3158
|
+
}
|
|
3065
3159
|
}
|
|
3066
3160
|
|
|
3067
3161
|
console.log(chalk.dim('─'.repeat(45)));
|
|
@@ -5028,6 +5122,7 @@ function formatNamespaceResponse(namespace, command, data) {
|
|
|
5028
5122
|
program
|
|
5029
5123
|
.command("help [command]")
|
|
5030
5124
|
.description("Show help for a command")
|
|
5125
|
+
.option("-b, --basic", "Show basic commands")
|
|
5031
5126
|
.option("-a, --advanced", "Show advanced commands (cart, AI, rewards)")
|
|
5032
5127
|
.option("--all", "Show all commands")
|
|
5033
5128
|
.action((commandName, opts) => {
|
|
@@ -5035,6 +5130,8 @@ program
|
|
|
5035
5130
|
showHelp(null, 'all');
|
|
5036
5131
|
} else if (opts.advanced) {
|
|
5037
5132
|
showHelp(null, 'advanced');
|
|
5133
|
+
} else if (opts.basic) {
|
|
5134
|
+
showHelp(null, 'basic');
|
|
5038
5135
|
} else {
|
|
5039
5136
|
showHelp(commandName, 'basic');
|
|
5040
5137
|
}
|
package/package.json
CHANGED
package/src/format.js
CHANGED
|
@@ -297,6 +297,20 @@ export function printOrders(orders) {
|
|
|
297
297
|
orders.forEach((order) => {
|
|
298
298
|
const date = new Date(order.createdAt).toLocaleDateString();
|
|
299
299
|
const status = order.status?.toLowerCase() || 'pending';
|
|
300
|
+
const storeNames = Array.isArray(order.storeNames)
|
|
301
|
+
? order.storeNames.filter(Boolean)
|
|
302
|
+
: [];
|
|
303
|
+
const itemLines = Array.isArray(order.items)
|
|
304
|
+
? order.items
|
|
305
|
+
.map((item) => {
|
|
306
|
+
const name = item?.product?.name || item?.productName || `Product #${item?.productId || '?'}`;
|
|
307
|
+
const qty = Number(item?.quantity || 1);
|
|
308
|
+
const unitPrice = Number(item?.priceAtPurchase ?? item?.price ?? item?.product?.price ?? 0);
|
|
309
|
+
const subtotal = qty * unitPrice;
|
|
310
|
+
return `${name} ×${qty} (${chalk.green('$' + subtotal.toFixed(2))})`;
|
|
311
|
+
})
|
|
312
|
+
.filter(Boolean)
|
|
313
|
+
: [];
|
|
300
314
|
|
|
301
315
|
// Status with color and icon
|
|
302
316
|
let statusDisplay;
|
|
@@ -317,6 +331,12 @@ export function printOrders(orders) {
|
|
|
317
331
|
console.log(chalk.white.bold(` ${order.orderNumber || '#' + order.id}`));
|
|
318
332
|
console.log(` ${chalk.dim('Date:')} ${date} ${chalk.dim('Total:')} ${chalk.green('$' + (order.total || 0))}`);
|
|
319
333
|
console.log(` ${statusDisplay}`);
|
|
334
|
+
if (storeNames.length > 0) {
|
|
335
|
+
console.log(` ${chalk.dim('Store:')} ${chalk.cyan(storeNames.join(', '))}`);
|
|
336
|
+
}
|
|
337
|
+
if (itemLines.length > 0) {
|
|
338
|
+
console.log(` ${chalk.dim('Items:')} ${itemLines.join(chalk.dim(' · '))}`);
|
|
339
|
+
}
|
|
320
340
|
if (order.deliveryMethod === 'digital') {
|
|
321
341
|
console.log(` ${chalk.dim('Download or key in library')}`);
|
|
322
342
|
}
|