terminalmarket 0.13.2 → 0.13.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/bin/tm.js +93 -108
- 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();
|
|
@@ -690,8 +739,8 @@ program
|
|
|
690
739
|
console.log("");
|
|
691
740
|
console.log(chalk.bold(`Total: $${total.toFixed(2)}`));
|
|
692
741
|
console.log("");
|
|
693
|
-
console.log(chalk.dim("To complete checkout,
|
|
694
|
-
console.log(chalk.dim("
|
|
742
|
+
console.log(chalk.dim("To complete checkout, use the web terminal checkout flow."));
|
|
743
|
+
console.log(chalk.dim(" https://terminalmarket.app"));
|
|
695
744
|
} catch (e) {
|
|
696
745
|
console.error(chalk.red(e?.message || String(e)));
|
|
697
746
|
process.exitCode = 1;
|
|
@@ -2854,39 +2903,13 @@ program
|
|
|
2854
2903
|
// help
|
|
2855
2904
|
// -----------------
|
|
2856
2905
|
|
|
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
|
-
};
|
|
2906
|
+
const cliHelpManifest = commandManifest?.cli || { quickStart: [], groups: [] };
|
|
2907
|
+
|
|
2908
|
+
function baseCommandName(commandSyntax = "") {
|
|
2909
|
+
if (!commandSyntax) return "";
|
|
2910
|
+
const clean = String(commandSyntax).trim().replace(/^tm\s+/, "");
|
|
2911
|
+
return clean.split(/\s+/)[0] || "";
|
|
2912
|
+
}
|
|
2890
2913
|
|
|
2891
2914
|
// Custom help formatter
|
|
2892
2915
|
function showHelp(commandName = null, mode = 'basic') {
|
|
@@ -2949,32 +2972,24 @@ function showHelp(commandName = null, mode = 'basic') {
|
|
|
2949
2972
|
return;
|
|
2950
2973
|
}
|
|
2951
2974
|
|
|
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
|
-
});
|
|
2975
|
+
// Collect declared commands for existence checks
|
|
2976
|
+
const available = new Set(program.commands.map((cmd) => cmd.name()));
|
|
2962
2977
|
|
|
2963
|
-
const COL_WIDTH =
|
|
2978
|
+
const COL_WIDTH = 34;
|
|
2964
2979
|
|
|
2965
|
-
const printGroup = (
|
|
2966
|
-
const groupCmds =
|
|
2967
|
-
.
|
|
2968
|
-
|
|
2980
|
+
const printGroup = (group, color) => {
|
|
2981
|
+
const groupCmds = (group.commands || []).filter((entry) =>
|
|
2982
|
+
available.has(baseCommandName(entry.command)),
|
|
2983
|
+
);
|
|
2969
2984
|
|
|
2970
2985
|
if (groupCmds.length === 0) return;
|
|
2971
2986
|
|
|
2972
|
-
console.log(color.bold(`${icon} ${
|
|
2973
|
-
groupCmds.forEach(
|
|
2974
|
-
const rawCmd =
|
|
2975
|
-
console.log(' ' + chalk.cyan(
|
|
2987
|
+
console.log(color.bold(`${group.icon || '•'} ${group.title}`));
|
|
2988
|
+
groupCmds.forEach((entry) => {
|
|
2989
|
+
const rawCmd = entry.command;
|
|
2990
|
+
console.log(' ' + chalk.cyan(entry.command) +
|
|
2976
2991
|
' '.repeat(Math.max(1, COL_WIDTH - rawCmd.length)) +
|
|
2977
|
-
chalk.dim(
|
|
2992
|
+
chalk.dim(entry.description || ""));
|
|
2978
2993
|
});
|
|
2979
2994
|
console.log();
|
|
2980
2995
|
};
|
|
@@ -2987,17 +3002,17 @@ function showHelp(commandName = null, mode = 'basic') {
|
|
|
2987
3002
|
if (mode === 'basic') {
|
|
2988
3003
|
// Simple, selling help
|
|
2989
3004
|
console.log(chalk.yellow.bold('Quick Start:'));
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
3005
|
+
for (const step of cliHelpManifest.quickStart || []) {
|
|
3006
|
+
const command = step.command || "";
|
|
3007
|
+
console.log(` ${chalk.green(command)}${' '.repeat(Math.max(1, 28 - command.length))}${chalk.dim(step.description || "")}`);
|
|
3008
|
+
}
|
|
2994
3009
|
console.log();
|
|
2995
3010
|
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3011
|
+
for (const group of cliHelpManifest.groups || []) {
|
|
3012
|
+
if (Array.isArray(group.levels) && group.levels.includes("basic")) {
|
|
3013
|
+
printGroup(group, chalk.white);
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
3001
3016
|
|
|
3002
3017
|
console.log(chalk.dim('─'.repeat(45)));
|
|
3003
3018
|
console.log(chalk.dim(' tm help --advanced') + chalk.dim(' cart, AI, rewards'));
|
|
@@ -3009,12 +3024,11 @@ function showHelp(commandName = null, mode = 'basic') {
|
|
|
3009
3024
|
console.log(chalk.yellow.bold('Advanced Features:'));
|
|
3010
3025
|
console.log();
|
|
3011
3026
|
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
printGroup('Automation', ['watch', 'telegram', 'alias', 'reward', 'subscribe', 'wishlist'], '👁', chalk.cyan);
|
|
3027
|
+
for (const group of cliHelpManifest.groups || []) {
|
|
3028
|
+
if (Array.isArray(group.levels) && group.levels.includes("advanced")) {
|
|
3029
|
+
printGroup(group, chalk.white);
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3018
3032
|
|
|
3019
3033
|
console.log(chalk.dim('─'.repeat(45)));
|
|
3020
3034
|
console.log(chalk.dim(' tm help') + chalk.dim(' basic commands'));
|
|
@@ -3026,42 +3040,10 @@ function showHelp(commandName = null, mode = 'basic') {
|
|
|
3026
3040
|
console.log(chalk.magenta.bold('Usage:'), chalk.green('tm'), chalk.cyan('<command>'), chalk.dim('[options]'));
|
|
3027
3041
|
console.log();
|
|
3028
3042
|
|
|
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);
|
|
3043
|
+
for (const group of cliHelpManifest.groups || []) {
|
|
3044
|
+
if (Array.isArray(group.levels) && group.levels.includes("all")) {
|
|
3045
|
+
printGroup(group, chalk.white);
|
|
3046
|
+
}
|
|
3065
3047
|
}
|
|
3066
3048
|
|
|
3067
3049
|
console.log(chalk.dim('─'.repeat(45)));
|
|
@@ -5028,6 +5010,7 @@ function formatNamespaceResponse(namespace, command, data) {
|
|
|
5028
5010
|
program
|
|
5029
5011
|
.command("help [command]")
|
|
5030
5012
|
.description("Show help for a command")
|
|
5013
|
+
.option("-b, --basic", "Show basic commands")
|
|
5031
5014
|
.option("-a, --advanced", "Show advanced commands (cart, AI, rewards)")
|
|
5032
5015
|
.option("--all", "Show all commands")
|
|
5033
5016
|
.action((commandName, opts) => {
|
|
@@ -5035,6 +5018,8 @@ program
|
|
|
5035
5018
|
showHelp(null, 'all');
|
|
5036
5019
|
} else if (opts.advanced) {
|
|
5037
5020
|
showHelp(null, 'advanced');
|
|
5021
|
+
} else if (opts.basic) {
|
|
5022
|
+
showHelp(null, 'basic');
|
|
5038
5023
|
} else {
|
|
5039
5024
|
showHelp(commandName, 'basic');
|
|
5040
5025
|
}
|
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
|
}
|