mercur-cli 0.1.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/README.md ADDED
@@ -0,0 +1,97 @@
1
+ ![Mercur Main Cover](https://cdn.prod.website-files.com/6790aeffc4b432ccaf1b56e5/67a225dc6fa298afc1cc4ae6_Mercur%20Cover.png)
2
+
3
+ <div align="center">
4
+ <h1>Mercur <br> Open Source Marketplace Platform</h1>
5
+ <!-- Shields.io Badges -->
6
+ <a href="https://github.com/mercurjs/mercur/tree/main?tab=MIT-1-ov-file">
7
+ <img alt="License" src="https://img.shields.io/badge/license-MIT-blue.svg" />
8
+ </a>
9
+ <a href="#">
10
+ <img alt="PRs Welcome" src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" />
11
+ </a>
12
+ <a href="https://rigbyjs.com/#contact">
13
+ <img alt="Support" src="https://img.shields.io/badge/support-contact%20author-blueviolet.svg" />
14
+ </a>
15
+ <!-- Website Links -->
16
+ <p>
17
+ <a href="https://mercurjs.com/">Mercur</a> | <a href="https://docs.mercurjs.com/">Docs</a>
18
+ </p>
19
+ </div>
20
+
21
+ # What is Mercur?
22
+
23
+ <a href="https://www.mercurjs.com/">Mercur</a> is the first truly limitless open source marketplace platform that combines the simplicity of SaaS with the freedom of open source. Built on [MedusaJS](https://github.com/medusajs/medusa) 2.0, it empowers businesses to create custom marketplaces without choosing between ownership and ease of use.
24
+
25
+ Mercur is a platform to start, customize, manage, and scale your marketplace for every business model with a modern technology stack.
26
+
27
+ ## Why Choose Mercur?
28
+
29
+ - Full Ownership: Unlike SaaS platforms, you own your marketplace with no transaction fees or vendor lock-in
30
+ - Modern Foundation: Built on MedusaJS, offering a modern tech stack that developers love
31
+ - Beautiful by Default: Create stunning storefronts without sacrificing customization
32
+
33
+ ## Power Any Marketplace Model
34
+
35
+ - Custom B2B Marketplace: Build enterprise-grade platforms with specialized workflows
36
+ - Custom B2C Marketplace: Create engaging consumer marketplaces with modern UX
37
+ - eCommerce Extension: Transform your store into a marketplace (coming soon)
38
+
39
+ ![Mercur Use Cases](https://cdn.prod.website-files.com/6790aeffc4b432ccaf1b56e5/67b46aa08180d5b8499c6a15_Use-cases.jpg)
40
+ &nbsp;
41
+
42
+ # Ready-to-go marketplace features
43
+
44
+ <b>Storefronts for Marketplace </b> <br>
45
+ Customizable storefronts designed for B2B and B2C with all elements including browsing and buying products across multiple vendors at once.
46
+
47
+ Discover <a href="https://github.com/mercurjs/b2c-marketplace-storefront">B2C Storefront Repository</a> - <a href="https://b2c.mercurjs.com/">🛍️ Check demo </a>
48
+
49
+ <b>Admin Panel</b> <br>
50
+ Control over whole marketplace: setting product categories, vendors, commissions and rules
51
+
52
+ <b>Vendor Panel</b> <br>
53
+ A powerful dashboard giving sellers complete control over their products, orders, and store management in one intuitive interface.
54
+
55
+ <b>Integrations</b> <br>
56
+ Built-in integration with Stripe for payments and Resend for communication needs. More integrations coming soon.
57
+
58
+ ![Mercur](https://cdn.prod.website-files.com/6790aeffc4b432ccaf1b56e5/67a1020f202572832c954ead_6b96703adfe74613f85133f83a19b1f0_Fleek%20Tilt%20-%20Readme.png)
59
+
60
+ &nbsp;
61
+
62
+ ## Quickstart
63
+
64
+ ```bash
65
+ # Install cli globally via npm
66
+ npm i -g mercur-cli
67
+
68
+ # Run mercur-cli, the installation script will ask you about database configuration
69
+ mercur-cli install
70
+
71
+ # After the installation script finishes, move to newly created directory
72
+ cd <yourProjectName>
73
+
74
+ # Run Mercur components
75
+ mercur-cli dev
76
+
77
+ ```
78
+
79
+ &nbsp;
80
+
81
+ ## Prerequisites
82
+
83
+ - Node.js v20+
84
+ - PostgreSQL
85
+ - Git CLI
86
+
87
+ # Resources
88
+
89
+ #### Learn more about Mercur
90
+
91
+ - [Mercur Website](https://www.mercurjs.com/)
92
+ - [Mercur Docs](https://docs.mercurjs.com/introduction)
93
+
94
+ #### Learn more about Medusa
95
+
96
+ - [Medusa Website](https://www.medusajs.com/)
97
+ - [Medusa Docs](https://docs.medusajs.com/v2)
@@ -0,0 +1,69 @@
1
+ import { execa } from "execa";
2
+ import fs from "fs-extra";
3
+ import path from "path";
4
+ import ora from "ora";
5
+
6
+ export async function backendSetup(options) {
7
+ const targetDir = options.directory;
8
+ const spinner = ora("Setting up Mercur backend...").start();
9
+
10
+ await execa("yarn", ["generate:oas"], {
11
+ cwd: path.join(targetDir, "backend/apps/backend"),
12
+ });
13
+ await execa("yarn", ["codegen"], {
14
+ cwd: path.join(targetDir, "backend"),
15
+ });
16
+ const DB_URL = `postgres://${options.db_user}:${options.db_pass}@${options.db_url}:${options.db_port}/${options.db_name}`;
17
+
18
+ await fs.writeFile(
19
+ path.join(targetDir, "backend/apps/backend/.env"),
20
+ `STORE_CORS=http://localhost:3000
21
+ ADMIN_CORS=http://localhost:9000
22
+ VENDOR_CORS=http://localhost:5173
23
+ AUTH_CORS=http://localhost:9000,http://localhost:5173,http://localhost:3000
24
+ REDIS_URL=redis://localhost:6379
25
+ JWT_SECRET=supersecret
26
+ COOKIE_SECRET=supersecret
27
+ DATABASE_URL=${DB_URL}
28
+
29
+ ALGOLIA_APP_ID=XXX
30
+ ALGOLIA_API_KEY=supersecret
31
+
32
+ STRIPE_SECRET_API_KEY=supersecret
33
+ STRIPE_CONNECTED_ACCOUNTS_WEBHOOK_SECRET=supersecret
34
+
35
+ RESEND_API_KEY=supersecret
36
+ RESEND_FROM_EMAIL=onboarding@resend.dev
37
+ `
38
+ );
39
+
40
+ spinner.text = "Setting up database...";
41
+ await execa("npx", ["medusa", "db:create", "--db", options.db_name], {
42
+ cwd: path.join(targetDir, "backend/apps/backend"),
43
+ });
44
+
45
+ spinner.text = "Running migrations...";
46
+ await execa("yarn", ["db:migrate"], {
47
+ cwd: path.join(targetDir, "backend/apps/backend"),
48
+ });
49
+
50
+ spinner.text = "Seeding data...";
51
+
52
+ await execa(
53
+ "npx",
54
+ ["medusa", "user", "--email", "admin@mercurjs.com", "--password", "admin"],
55
+ {
56
+ cwd: path.join(targetDir, "backend/apps/backend"),
57
+ }
58
+ );
59
+
60
+ const result = await execa("yarn", ["seed"], {
61
+ cwd: path.join(targetDir, "backend/apps/backend"),
62
+ });
63
+
64
+ const pkstart = result.stdout.indexOf("pk_");
65
+ const publishableKey = result.stdout.substring(pkstart, pkstart + 67);
66
+
67
+ spinner.succeed("Backend ready!");
68
+ return publishableKey;
69
+ }
@@ -0,0 +1,41 @@
1
+ import fs from "fs-extra";
2
+ import path from "path";
3
+ import ora from "ora";
4
+
5
+ export async function storefrontSetup(options) {
6
+ const targetDir = options.directory;
7
+ const spinner = ora("Setting up Mercur storefront...").start();
8
+
9
+ await fs.writeFile(
10
+ path.join(targetDir, "storefront/.env.local"),
11
+ `MEDUSA_BACKEND_URL=http://localhost:9000
12
+ NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=${options.publishableKey}
13
+ NEXT_PUBLIC_BASE_URL=http://localhost:3000
14
+ NEXT_PUBLIC_DEFAULT_REGION=pl
15
+ NEXT_PUBLIC_STRIPE_KEY=supersecret
16
+ REVALIDATE_SECRET=supersecret
17
+ NEXT_PUBLIC_SITE_NAME="Mercur Marketplace"
18
+ NEXT_PUBLIC_SITE_DESCRIPTION="Mercur Marketplace"
19
+ NEXT_PUBLIC_ALGOLIA_ID=
20
+ NEXT_PUBLIC_ALGOLIA_SEARCH_KEY=`
21
+ );
22
+
23
+ spinner.succeed("Storefront ready!");
24
+ }
25
+
26
+ export async function vendorPanelSetup(options) {
27
+ const targetDir = options.directory;
28
+ const spinner = ora("Setting up Mercur vendor panel...").start();
29
+
30
+ await fs.writeFile(
31
+ path.join(targetDir, "vendor-panel/.env"),
32
+ `VITE_MEDUSA_BASE=/
33
+ VITE_MEDUSA_STOREFRONT_URL=http://localhost:3000
34
+ VITE_MEDUSA_BACKEND_URL=http://localhost:9000
35
+ VITE_PUBLISHABLE_API_KEY=
36
+ VITE_TALK_JS_APP_ID=
37
+ VITE_DISABLE_SELLERS_REGISTRATION=false`
38
+ );
39
+
40
+ spinner.succeed("Vendor panel ready!");
41
+ }
@@ -0,0 +1,102 @@
1
+ import chalk from "chalk";
2
+ import inquirer from "inquirer";
3
+ import { pullAndInstall } from "./pull-and-install.js";
4
+ import { backendSetup } from "./backend-setup.js";
5
+ import { storefrontSetup, vendorPanelSetup } from "./frontend-setup.js";
6
+
7
+ export async function fullInstall() {
8
+ const { project_name } = await inquirer.prompt({
9
+ type: "input",
10
+ name: "project_name",
11
+ message: "What is your project name?",
12
+ default: "mercur",
13
+ });
14
+
15
+ const { install_storefront } = await inquirer.prompt({
16
+ type: "confirm",
17
+ name: "install_storefront",
18
+ message: "Install storefront?",
19
+ default: true,
20
+ });
21
+
22
+ const { install_vendor } = await inquirer.prompt({
23
+ type: "confirm",
24
+ name: "install_vendor",
25
+ message: "Install vendor panel?",
26
+ default: true,
27
+ });
28
+
29
+ const { db_url } = await inquirer.prompt({
30
+ type: "input",
31
+ name: "db_url",
32
+ message: "Database address:",
33
+ default: "localhost",
34
+ });
35
+
36
+ const { db_port } = await inquirer.prompt({
37
+ type: "input",
38
+ name: "db_port",
39
+ message: "Database port:",
40
+ default: "5432",
41
+ });
42
+
43
+ const { db_user } = await inquirer.prompt({
44
+ type: "input",
45
+ name: "db_user",
46
+ message: "Database user:",
47
+ default: "postgres",
48
+ });
49
+
50
+ const { db_pass } = await inquirer.prompt({
51
+ type: "input",
52
+ name: "db_pass",
53
+ message: "Database password:",
54
+ default: "postgres",
55
+ });
56
+
57
+ const { db_name } = await inquirer.prompt({
58
+ type: "input",
59
+ name: "db_name",
60
+ message: "Database name:",
61
+ default: "mercurjs",
62
+ });
63
+
64
+ console.log(chalk.blue("Downloading Mercur"));
65
+ await pullAndInstall({
66
+ directory: project_name,
67
+ install_storefront,
68
+ install_vendor,
69
+ });
70
+ console.log(chalk.blue("Setting up Mercur"));
71
+ const publishableKey = await backendSetup({
72
+ db_name,
73
+ db_pass,
74
+ db_port,
75
+ db_url,
76
+ db_user,
77
+ directory: project_name,
78
+ });
79
+
80
+ if (install_storefront) {
81
+ await storefrontSetup({ directory: project_name, publishableKey });
82
+ }
83
+
84
+ if (install_vendor) {
85
+ await vendorPanelSetup({ directory: project_name });
86
+ }
87
+
88
+ console.log(chalk.greenBright("=== Mercur ready! ==="));
89
+ console.log(chalk.blue("Here are your credentials:"));
90
+ console.log(`
91
+ ${chalk.bold("Admin panel:")}
92
+ login: ${chalk.cyanBright("admin@mercurjs.com")}
93
+ password: ${chalk.cyanBright("admin")}
94
+
95
+ `);
96
+ console.log(`
97
+ ${chalk.bold("Vendor panel:")}
98
+ login: ${chalk.cyanBright("seller@mercurjs.com")}
99
+ password: ${chalk.cyanBright("secret")}
100
+
101
+ `);
102
+ }
@@ -0,0 +1,55 @@
1
+ import { execa } from "execa";
2
+ import fs from "fs-extra";
3
+ import path from "path";
4
+ import ora from "ora";
5
+
6
+ export async function pullAndInstall(options) {
7
+ const targetDir = path.resolve(process.cwd(), options.directory);
8
+
9
+ const spinner = ora("Setting up Mercur...").start();
10
+ await fs.ensureDir(targetDir);
11
+
12
+ spinner.text = "Installing Mercur backend...";
13
+ await execa(
14
+ "git",
15
+ ["clone", "https://github.com/mercurjs/mercur.git", "backend"],
16
+ {
17
+ cwd: targetDir,
18
+ }
19
+ );
20
+ await execa("yarn", ["install"], { cwd: path.join(targetDir, "backend") });
21
+
22
+ if (options.install_storefront) {
23
+ spinner.text = "Installing Mercur storefront...";
24
+ await execa(
25
+ "git",
26
+ [
27
+ "clone",
28
+ "https://github.com/mercurjs/b2c-marketplace-storefront.git",
29
+ "storefront",
30
+ ],
31
+ {
32
+ cwd: targetDir,
33
+ }
34
+ );
35
+ await execa("yarn", ["install"], {
36
+ cwd: path.join(targetDir, "storefront"),
37
+ });
38
+ }
39
+
40
+ if (options.install_vendor) {
41
+ spinner.text = "Installing Mercur vendor panel...";
42
+ await execa(
43
+ "git",
44
+ ["clone", "https://github.com/mercurjs/vendor-panel.git", "vendor-panel"],
45
+ {
46
+ cwd: targetDir,
47
+ }
48
+ );
49
+ await execa("npm", ["install"], {
50
+ cwd: path.join(targetDir, "vendor-panel"),
51
+ });
52
+ }
53
+
54
+ spinner.succeed("Download complete!");
55
+ }
package/cli/start.js ADDED
@@ -0,0 +1,61 @@
1
+ import { execa } from "execa";
2
+ import ora from "ora";
3
+ import chalk from "chalk";
4
+ import path from "path";
5
+ import fs from "fs-extra";
6
+
7
+ export async function startAll() {
8
+ const spinner = ora("Starting Mercur development environment...").start();
9
+
10
+ const backendExists = fs.existsSync("backend");
11
+ const storefrontExists = fs.existsSync("storefront");
12
+ const vendorExists = fs.existsSync("vendor-panel");
13
+
14
+ if (!backendExists) {
15
+ spinner.fail("Mercur backend not detected!");
16
+ process.exit();
17
+ }
18
+
19
+ const servicesToRun = [];
20
+
21
+ spinner.text = "Starting Mercur backend...";
22
+ const backend = execa("yarn", ["dev"], {
23
+ cwd: path.join(process.cwd(), "backend/apps/backend"),
24
+ });
25
+ servicesToRun.push(backend);
26
+
27
+ if (storefrontExists) {
28
+ spinner.text = "Starting Mercur storefront...";
29
+ const storefront = execa("npm", ["run", "dev"], {
30
+ cwd: path.join(process.cwd(), "storefront"),
31
+ });
32
+ servicesToRun.push(storefront);
33
+ }
34
+
35
+ if (vendorExists) {
36
+ spinner.text = "Starting vendor panel...";
37
+ const vendorPanel = execa("npm", ["run", "dev"], {
38
+ cwd: path.join(process.cwd(), "vendor-panel"),
39
+ });
40
+ servicesToRun.push(vendorPanel);
41
+ }
42
+
43
+ spinner.succeed(chalk.green("Development environment started!"));
44
+ console.log(chalk.blue("\nServices:"));
45
+ console.log("- Backend: http://localhost:9000");
46
+ if (storefrontExists) {
47
+ console.log("- B2C Storefront: http://localhost:3000");
48
+ }
49
+
50
+ if (vendorExists) {
51
+ console.log("- Vendor Panel: http://localhost:7001");
52
+ }
53
+
54
+ process.on("SIGINT", async () => {
55
+ console.log(chalk.yellow("\nShutting down services..."));
56
+ servicesToRun.forEach((service) => service.kill());
57
+ process.exit(0);
58
+ });
59
+
60
+ await Promise.all(servicesToRun);
61
+ }
package/index.js ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+
3
+ import chalk from "chalk";
4
+ import { program } from "commander";
5
+ import { fullInstall } from "./cli/full-install.js";
6
+ import { startAll } from "./cli/start.js";
7
+ import { backendSetup } from "./cli/backend-setup.js";
8
+
9
+ console.log(
10
+ chalk.blue(`
11
+ ╔═══════════════════════════════════════════════╗
12
+ ║ ║
13
+ ║ ${chalk.bold("Mercur - Open Source Marketplace Platform")} ║
14
+ ║ ║
15
+ ╚═══════════════════════════════════════════════╝
16
+ `)
17
+ );
18
+
19
+ program
20
+ .command("be-setup")
21
+ .version("1.0.0")
22
+ .option("-d, --directory <type>", "Mercur directory")
23
+ .option("-db_url, --db_url <type>", "DB_URL", "localhost")
24
+ .option("-db_port, --db_port <type>", "DB_URL", "5432")
25
+ .option("-db_user, --db_user <type>", "DB_URL", "postgres")
26
+ .option("-db_pass, --db_pass <type>", "DB_URL", "postgres")
27
+ .option("-db_name, --db_name <type>", "DB_URL", "mercur-clis")
28
+ .action(async (opts) => {
29
+ await backendSetup(opts);
30
+ });
31
+
32
+ program
33
+ .command("install")
34
+ .version("1.0.0")
35
+ .description("Perform full installation of Mercur")
36
+ .action(fullInstall);
37
+
38
+ program
39
+ .command("dev")
40
+ .version("1.0.0")
41
+ .description("Start all Mercur components")
42
+ .action(startAll);
43
+
44
+ program.parse(process.argv);
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "mercur-cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI for Mercur - Open Source Marketplace Platform",
5
+ "main": "index.js",
6
+ "license": "MIT",
7
+ "bin": {
8
+ "mercur-cli": "./index.js"
9
+ },
10
+ "author": "MercurJS <hello@mercurjs.com> (https://mercurjs.com)",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/mercurjs/mercur"
14
+ },
15
+ "keywords": [
16
+ "mercur",
17
+ "marketplace",
18
+ "medusajs"
19
+ ],
20
+ "type": "module",
21
+ "scripts": {},
22
+ "dependencies": {
23
+ "chalk": "^4.1.2",
24
+ "commander": "^11.1.0",
25
+ "execa": "^9.5.2",
26
+ "fs-extra": "^11.2.0",
27
+ "inquirer": "^8.2.6",
28
+ "ora": "^5.4.1"
29
+ },
30
+ "devDependencies": {
31
+ "@types/fs-extra": "^11.0.4",
32
+ "@types/inquirer": "^8.2.10",
33
+ "@types/node": "^20.11.0",
34
+ "tsup": "^8.0.2",
35
+ "typescript": "^5.3.3"
36
+ }
37
+ }