create-x402-app 0.1.1

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.
Files changed (3) hide show
  1. package/README.md +81 -0
  2. package/dist/index.js +374 -0
  3. package/package.json +52 -0
package/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # create-x402-app
2
+
3
+ Create a new x402 pay-per-request API project with one command.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npx create-x402-app my-app
9
+ cd my-app
10
+ npm run dev
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ### Interactive Mode
16
+
17
+ ```bash
18
+ npx create-x402-app
19
+ ```
20
+
21
+ This will prompt you for:
22
+ - Project name
23
+ - Package manager (npm, yarn, pnpm, bun)
24
+ - Whether to install dependencies
25
+
26
+ ### With Arguments
27
+
28
+ ```bash
29
+ # Create project with specific name
30
+ npx create-x402-app my-api
31
+
32
+ # Use specific package manager
33
+ npx create-x402-app my-api --bun
34
+ npx create-x402-app my-api --pnpm
35
+ npx create-x402-app my-api --yarn
36
+
37
+ # Skip dependency installation
38
+ npx create-x402-app my-api --skip-install
39
+ ```
40
+
41
+ ## What's Included
42
+
43
+ The generated project includes:
44
+
45
+ - **Next.js 16** with App Router
46
+ - **x402-mantle-sdk** for HTTP 402 payments
47
+ - **TypeScript** configuration
48
+ - **Tailwind CSS** for styling
49
+ - **Example API routes**:
50
+ - `/api/info` - Free endpoint
51
+ - `/api/premium` - Paid endpoint (0.001 MNT)
52
+ - `/api/weather` - Paid endpoint (0.0005 MNT)
53
+ - **Demo frontend** with wallet connection
54
+
55
+ ## After Creating
56
+
57
+ 1. **Get your App ID**
58
+ - Visit [https://mantle-x402.vercel.app](https://mantle-x402.vercel.app)
59
+ - Connect your wallet
60
+ - Create a project
61
+ - Copy your App ID
62
+
63
+ 2. **Configure environment**
64
+ ```bash
65
+ cp .env.example .env
66
+ # Edit .env with your App ID
67
+ ```
68
+
69
+ 3. **Start development**
70
+ ```bash
71
+ npm run dev
72
+ ```
73
+
74
+ ## Learn More
75
+
76
+ - [x402 Documentation](https://mantle-x402.vercel.app)
77
+ - [x402-mantle-sdk on npm](https://www.npmjs.com/package/x402-mantle-sdk)
78
+
79
+ ## License
80
+
81
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,374 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+
29
+ // package.json
30
+ var require_package = __commonJS({
31
+ "package.json"(exports2, module2) {
32
+ module2.exports = {
33
+ name: "create-x402-app",
34
+ version: "0.1.1",
35
+ description: "Create a new x402 pay-per-request API project",
36
+ keywords: [
37
+ "x402",
38
+ "http-402",
39
+ "payment",
40
+ "api",
41
+ "mantle",
42
+ "web3",
43
+ "blockchain",
44
+ "create",
45
+ "cli",
46
+ "boilerplate",
47
+ "starter"
48
+ ],
49
+ author: "",
50
+ license: "MIT",
51
+ repository: {
52
+ type: "git",
53
+ url: "https://github.com/anthropics/x402"
54
+ },
55
+ bin: {
56
+ "create-x402-app": "./dist/index.js"
57
+ },
58
+ files: [
59
+ "dist",
60
+ "template"
61
+ ],
62
+ scripts: {
63
+ build: "tsup",
64
+ dev: "tsup --watch",
65
+ prepublishOnly: "npm run build"
66
+ },
67
+ dependencies: {
68
+ "@types/figlet": "^1.7.0",
69
+ chalk: "^5.3.0",
70
+ commander: "^12.1.0",
71
+ figlet: "^1.9.4",
72
+ "fs-extra": "^11.2.0",
73
+ ora: "^8.0.1",
74
+ prompts: "^2.4.2"
75
+ },
76
+ devDependencies: {
77
+ "@types/fs-extra": "^11.0.4",
78
+ "@types/node": "^20.0.0",
79
+ "@types/prompts": "^2.4.9",
80
+ tsup: "^8.0.0",
81
+ typescript: "^5.0.0"
82
+ }
83
+ };
84
+ }
85
+ });
86
+
87
+ // src/index.ts
88
+ var import_commander = require("commander");
89
+ var import_chalk = __toESM(require("chalk"));
90
+ var import_ora = __toESM(require("ora"));
91
+ var import_prompts = __toESM(require("prompts"));
92
+ var import_fs_extra = __toESM(require("fs-extra"));
93
+ var import_path = __toESM(require("path"));
94
+ var import_child_process = require("child_process");
95
+ var import_figlet = __toESM(require("figlet"));
96
+ var packageJson = require_package();
97
+ function getTemplateDir(projectType, framework) {
98
+ return `${projectType}-${framework}`;
99
+ }
100
+ function showBanner() {
101
+ return new Promise((resolve) => {
102
+ import_figlet.default.text("x402", {
103
+ font: "ANSI Shadow",
104
+ horizontalLayout: "default",
105
+ verticalLayout: "default"
106
+ }, (err, data) => {
107
+ console.log();
108
+ if (!err && data) {
109
+ const lines = data.split("\n");
110
+ const colors = [import_chalk.default.hex("#00D4FF"), import_chalk.default.hex("#00BFFF"), import_chalk.default.hex("#00A5FF"), import_chalk.default.hex("#008BFF"), import_chalk.default.hex("#0070FF"), import_chalk.default.hex("#0055FF"), import_chalk.default.hex("#003AFF")];
111
+ lines.forEach((line, i) => {
112
+ const color = colors[Math.min(i, colors.length - 1)];
113
+ console.log(color(line));
114
+ });
115
+ } else {
116
+ console.log(import_chalk.default.bold.cyan(" x402"));
117
+ }
118
+ console.log();
119
+ console.log(import_chalk.default.bold.white(" mantle-sdk"));
120
+ console.log();
121
+ console.log(import_chalk.default.gray(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E"));
122
+ console.log(import_chalk.default.gray(" \u2502"), import_chalk.default.cyan(" Build pay-per-request APIs with HTTP 402 protocol "), import_chalk.default.gray("\u2502"));
123
+ console.log(import_chalk.default.gray(" \u2502"), import_chalk.default.white(" Powered by Mantle Network "), import_chalk.default.gray("\u2502"));
124
+ console.log(import_chalk.default.gray(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
125
+ console.log();
126
+ console.log(import_chalk.default.gray(` v${packageJson.version}`));
127
+ console.log();
128
+ resolve();
129
+ });
130
+ });
131
+ }
132
+ async function main() {
133
+ await showBanner();
134
+ import_commander.program.name("create-x402-app").description("Create a new x402 pay-per-request API project").version(packageJson.version).argument("[project-name]", "Name of your project").option("--fullstack", "Create a fullstack project").option("--backend", "Create a backend-only project").option("--hono", "Use Hono framework").option("--express", "Use Express framework").option("--npm", "Use npm as package manager").option("--yarn", "Use yarn as package manager").option("--pnpm", "Use pnpm as package manager").option("--bun", "Use bun as package manager").option("--skip-install", "Skip installing dependencies").parse();
135
+ const args = import_commander.program.args;
136
+ const options = import_commander.program.opts();
137
+ let projectName = args[0];
138
+ let projectType;
139
+ let framework;
140
+ let packageManager = "npm";
141
+ let installDeps = !options.skipInstall;
142
+ if (options.fullstack) projectType = "fullstack";
143
+ if (options.backend) projectType = "backend";
144
+ if (options.hono) framework = "hono";
145
+ if (options.express) framework = "express";
146
+ let packageManagerFromFlag = false;
147
+ if (options.npm) {
148
+ packageManager = "npm";
149
+ packageManagerFromFlag = true;
150
+ } else if (options.yarn) {
151
+ packageManager = "yarn";
152
+ packageManagerFromFlag = true;
153
+ } else if (options.pnpm) {
154
+ packageManager = "pnpm";
155
+ packageManagerFromFlag = true;
156
+ } else if (options.bun) {
157
+ packageManager = "bun";
158
+ packageManagerFromFlag = true;
159
+ }
160
+ if (!projectName) {
161
+ const { name } = await (0, import_prompts.default)({
162
+ type: "text",
163
+ name: "name",
164
+ message: "What is your project name?",
165
+ initial: "my-x402-app",
166
+ validate: (value) => {
167
+ if (!value) return "Project name is required";
168
+ if (!/^[a-z0-9-_]+$/i.test(value)) {
169
+ return "Project name can only contain letters, numbers, hyphens, and underscores";
170
+ }
171
+ return true;
172
+ }
173
+ }, {
174
+ onCancel: () => {
175
+ console.log(import_chalk.default.red("\n\u2716 Project creation cancelled."));
176
+ process.exit(1);
177
+ }
178
+ });
179
+ projectName = name;
180
+ }
181
+ if (!projectType) {
182
+ const { type } = await (0, import_prompts.default)({
183
+ type: "select",
184
+ name: "type",
185
+ message: "What type of project?",
186
+ choices: [
187
+ {
188
+ title: "Fullstack",
189
+ value: "fullstack",
190
+ description: "Next.js frontend + API routes with x402"
191
+ },
192
+ {
193
+ title: "Backend only",
194
+ value: "backend",
195
+ description: "Standalone API server with x402"
196
+ }
197
+ ],
198
+ initial: 0
199
+ }, {
200
+ onCancel: () => {
201
+ console.log(import_chalk.default.red("\n\u2716 Project creation cancelled."));
202
+ process.exit(1);
203
+ }
204
+ });
205
+ projectType = type;
206
+ }
207
+ if (!framework) {
208
+ const { fw } = await (0, import_prompts.default)({
209
+ type: "select",
210
+ name: "fw",
211
+ message: "Which framework?",
212
+ choices: [
213
+ {
214
+ title: "Hono",
215
+ value: "hono",
216
+ description: "Fast, lightweight, Web Standards"
217
+ },
218
+ {
219
+ title: "Express",
220
+ value: "express",
221
+ description: "Popular, mature, extensive ecosystem"
222
+ }
223
+ ],
224
+ initial: 0
225
+ }, {
226
+ onCancel: () => {
227
+ console.log(import_chalk.default.red("\n\u2716 Project creation cancelled."));
228
+ process.exit(1);
229
+ }
230
+ });
231
+ framework = fw;
232
+ }
233
+ if (!packageManagerFromFlag) {
234
+ const response = await (0, import_prompts.default)([
235
+ {
236
+ type: "select",
237
+ name: "packageManager",
238
+ message: "Package manager:",
239
+ choices: [
240
+ { title: "npm", value: "npm" },
241
+ { title: "yarn", value: "yarn" },
242
+ { title: "pnpm", value: "pnpm" },
243
+ { title: "bun", value: "bun" }
244
+ ],
245
+ initial: 0
246
+ },
247
+ {
248
+ type: "confirm",
249
+ name: "installDeps",
250
+ message: "Install dependencies?",
251
+ initial: true
252
+ }
253
+ ], {
254
+ onCancel: () => {
255
+ console.log(import_chalk.default.red("\n\u2716 Project creation cancelled."));
256
+ process.exit(1);
257
+ }
258
+ });
259
+ packageManager = response.packageManager;
260
+ installDeps = response.installDeps;
261
+ }
262
+ if (!projectName || !projectType || !framework) {
263
+ console.log(import_chalk.default.red("\n\u2716 Missing required options."));
264
+ process.exit(1);
265
+ }
266
+ const projectPath = import_path.default.resolve(process.cwd(), projectName);
267
+ const templateName = getTemplateDir(projectType, framework);
268
+ console.log();
269
+ console.log(import_chalk.default.bold(" Project Configuration"));
270
+ console.log(import_chalk.default.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
271
+ console.log(import_chalk.default.gray(" Name: "), import_chalk.default.cyan(projectName));
272
+ console.log(import_chalk.default.gray(" Type: "), import_chalk.default.white(projectType));
273
+ console.log(import_chalk.default.gray(" Framework:"), import_chalk.default.white(framework));
274
+ console.log(import_chalk.default.gray(" Package: "), import_chalk.default.white(packageManager));
275
+ console.log();
276
+ if (import_fs_extra.default.existsSync(projectPath)) {
277
+ const { overwrite } = await (0, import_prompts.default)({
278
+ type: "confirm",
279
+ name: "overwrite",
280
+ message: `Directory ${import_chalk.default.cyan(projectName)} already exists. Overwrite?`,
281
+ initial: false
282
+ });
283
+ if (!overwrite) {
284
+ console.log(import_chalk.default.red("\n\u2716 Project creation cancelled."));
285
+ process.exit(1);
286
+ }
287
+ import_fs_extra.default.removeSync(projectPath);
288
+ }
289
+ const spinner = (0, import_ora.default)("Creating project...").start();
290
+ try {
291
+ const templatePath = import_path.default.join(__dirname, "..", "templates", templateName);
292
+ if (!import_fs_extra.default.existsSync(templatePath)) {
293
+ spinner.fail(`Template not found: ${templateName}`);
294
+ console.log(import_chalk.default.yellow(`
295
+ Available templates:`));
296
+ const templatesDir = import_path.default.join(__dirname, "..", "templates");
297
+ if (import_fs_extra.default.existsSync(templatesDir)) {
298
+ const templates = import_fs_extra.default.readdirSync(templatesDir);
299
+ templates.forEach((t) => console.log(import_chalk.default.gray(` \u2022 ${t}`)));
300
+ }
301
+ process.exit(1);
302
+ }
303
+ import_fs_extra.default.copySync(templatePath, projectPath);
304
+ const pkgPath = import_path.default.join(projectPath, "package.json");
305
+ if (import_fs_extra.default.existsSync(pkgPath)) {
306
+ const pkg = import_fs_extra.default.readJsonSync(pkgPath);
307
+ pkg.name = projectName;
308
+ import_fs_extra.default.writeJsonSync(pkgPath, pkg, { spaces: 2 });
309
+ }
310
+ const gitignoreVariants = ["_gitignore", "gitignore"];
311
+ for (const variant of gitignoreVariants) {
312
+ const gitignorePath = import_path.default.join(projectPath, variant);
313
+ if (import_fs_extra.default.existsSync(gitignorePath)) {
314
+ import_fs_extra.default.renameSync(gitignorePath, import_path.default.join(projectPath, ".gitignore"));
315
+ break;
316
+ }
317
+ }
318
+ const envExampleVariants = ["_env.example", "env.example"];
319
+ for (const variant of envExampleVariants) {
320
+ const envExamplePath = import_path.default.join(projectPath, variant);
321
+ if (import_fs_extra.default.existsSync(envExamplePath)) {
322
+ import_fs_extra.default.renameSync(envExamplePath, import_path.default.join(projectPath, ".env.example"));
323
+ break;
324
+ }
325
+ }
326
+ spinner.succeed("Project created!");
327
+ if (installDeps) {
328
+ const installSpinner = (0, import_ora.default)("Installing dependencies...").start();
329
+ try {
330
+ const installCmd = {
331
+ npm: "npm install",
332
+ yarn: "yarn",
333
+ pnpm: "pnpm install",
334
+ bun: "bun install"
335
+ }[packageManager];
336
+ (0, import_child_process.execSync)(installCmd, {
337
+ cwd: projectPath,
338
+ stdio: "pipe"
339
+ });
340
+ installSpinner.succeed("Dependencies installed!");
341
+ } catch (error) {
342
+ installSpinner.fail("Failed to install dependencies");
343
+ console.log(import_chalk.default.yellow("\nYou can install them manually:"));
344
+ console.log(import_chalk.default.cyan(` cd ${projectName}`));
345
+ console.log(import_chalk.default.cyan(` ${packageManager} install`));
346
+ }
347
+ }
348
+ const runCmd = packageManager === "npm" ? "npm run" : packageManager;
349
+ console.log();
350
+ console.log(import_chalk.default.green.bold("\u2714 Success!"), `Created ${import_chalk.default.cyan(projectName)}`);
351
+ console.log();
352
+ console.log(import_chalk.default.bold(" Next steps:"));
353
+ console.log();
354
+ console.log(import_chalk.default.gray(" 1."), import_chalk.default.cyan(`cd ${projectName}`));
355
+ if (!installDeps) {
356
+ console.log(import_chalk.default.gray(" 2."), import_chalk.default.cyan(`${packageManager} install`));
357
+ console.log(import_chalk.default.gray(" 3."), import_chalk.default.cyan("cp .env.example .env"));
358
+ console.log(import_chalk.default.gray(" 4."), "Get your App ID from", import_chalk.default.underline("https://mantle-x402.vercel.app"));
359
+ console.log(import_chalk.default.gray(" 5."), import_chalk.default.cyan(`${runCmd} dev`));
360
+ } else {
361
+ console.log(import_chalk.default.gray(" 2."), import_chalk.default.cyan("cp .env.example .env"));
362
+ console.log(import_chalk.default.gray(" 3."), "Get your App ID from", import_chalk.default.underline("https://mantle-x402.vercel.app"));
363
+ console.log(import_chalk.default.gray(" 4."), import_chalk.default.cyan(`${runCmd} dev`));
364
+ }
365
+ console.log();
366
+ console.log(import_chalk.default.gray(" Documentation:"), import_chalk.default.underline("https://mantle-x402.vercel.app"));
367
+ console.log();
368
+ } catch (error) {
369
+ spinner.fail("Failed to create project");
370
+ console.error(error);
371
+ process.exit(1);
372
+ }
373
+ }
374
+ main().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "create-x402-app",
3
+ "version": "0.1.1",
4
+ "description": "Create a new x402 pay-per-request API project",
5
+ "keywords": [
6
+ "x402",
7
+ "http-402",
8
+ "payment",
9
+ "api",
10
+ "mantle",
11
+ "web3",
12
+ "blockchain",
13
+ "create",
14
+ "cli",
15
+ "boilerplate",
16
+ "starter"
17
+ ],
18
+ "author": "",
19
+ "license": "MIT",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/anthropics/x402"
23
+ },
24
+ "bin": {
25
+ "create-x402-app": "./dist/index.js"
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "template"
30
+ ],
31
+ "scripts": {
32
+ "build": "tsup",
33
+ "dev": "tsup --watch",
34
+ "prepublishOnly": "npm run build"
35
+ },
36
+ "dependencies": {
37
+ "@types/figlet": "^1.7.0",
38
+ "chalk": "^5.3.0",
39
+ "commander": "^12.1.0",
40
+ "figlet": "^1.9.4",
41
+ "fs-extra": "^11.2.0",
42
+ "ora": "^8.0.1",
43
+ "prompts": "^2.4.2"
44
+ },
45
+ "devDependencies": {
46
+ "@types/fs-extra": "^11.0.4",
47
+ "@types/node": "^20.0.0",
48
+ "@types/prompts": "^2.4.9",
49
+ "tsup": "^8.0.0",
50
+ "typescript": "^5.0.0"
51
+ }
52
+ }