run402 1.8.0 → 1.8.2
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/cli.mjs +3 -3
- package/lib/agent.mjs +4 -22
- package/lib/apps.mjs +4 -22
- package/lib/config.mjs +10 -0
- package/lib/deploy.mjs +15 -42
- package/lib/init.mjs +1 -1
- package/lib/message.mjs +4 -22
- package/lib/projects.mjs +5 -25
- package/lib/sites.mjs +5 -23
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -17,7 +17,7 @@ Commands:
|
|
|
17
17
|
wallet Manage your x402 wallet (create, fund, balance, status)
|
|
18
18
|
tier Manage tier subscription (status, set)
|
|
19
19
|
projects Manage projects (provision, list, query, inspect, delete)
|
|
20
|
-
deploy Deploy a full-stack app or static site (
|
|
20
|
+
deploy Deploy a full-stack app or static site (requires active tier)
|
|
21
21
|
functions Manage serverless functions (deploy, invoke, logs, list, delete)
|
|
22
22
|
secrets Manage project secrets (set, list, delete)
|
|
23
23
|
storage Manage file storage (upload, download, list, delete)
|
|
@@ -33,7 +33,7 @@ Run 'run402 <command> --help' for detailed usage of each command.
|
|
|
33
33
|
Examples:
|
|
34
34
|
run402 wallet create
|
|
35
35
|
run402 wallet fund
|
|
36
|
-
run402 deploy --
|
|
36
|
+
run402 deploy --manifest app.json
|
|
37
37
|
run402 projects list
|
|
38
38
|
run402 projects sql <project_id> "SELECT * FROM users LIMIT 5"
|
|
39
39
|
run402 functions deploy <project_id> my-fn --code handler.ts
|
|
@@ -43,7 +43,7 @@ Examples:
|
|
|
43
43
|
Getting started:
|
|
44
44
|
run402 init Set up everything in one command
|
|
45
45
|
run402 tier set prototype Subscribe to a tier
|
|
46
|
-
run402 deploy
|
|
46
|
+
run402 deploy --manifest app.json
|
|
47
47
|
`;
|
|
48
48
|
|
|
49
49
|
if (!cmd || cmd === '--help' || cmd === '-h') {
|
package/lib/agent.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { existsSync } from "fs";
|
|
1
|
+
import { API, walletAuthHeaders } from "./config.mjs";
|
|
3
2
|
|
|
4
3
|
const HELP = `run402 agent — Manage agent identity
|
|
5
4
|
|
|
@@ -24,32 +23,15 @@ async function contact(args) {
|
|
|
24
23
|
if (args[i] === "--webhook" && args[i + 1]) webhook = args[++i];
|
|
25
24
|
}
|
|
26
25
|
if (!name) { console.error(JSON.stringify({ status: "error", message: "Missing --name <name>" })); process.exit(1); }
|
|
27
|
-
|
|
28
|
-
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const wallet = readWallet();
|
|
33
|
-
const { privateKeyToAccount } = await import("viem/accounts");
|
|
34
|
-
const { createPublicClient, http } = await import("viem");
|
|
35
|
-
const { baseSepolia } = await import("viem/chains");
|
|
36
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
37
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
38
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
39
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
40
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
41
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
42
|
-
const client = new x402Client();
|
|
43
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
44
|
-
const fetchPaid = wrapFetchWithPayment(fetch, client);
|
|
26
|
+
const authHeaders = await walletAuthHeaders();
|
|
45
27
|
|
|
46
28
|
const body = { name };
|
|
47
29
|
if (email) body.email = email;
|
|
48
30
|
if (webhook) body.webhook = webhook;
|
|
49
31
|
|
|
50
|
-
const res = await
|
|
32
|
+
const res = await fetch(`${API}/agent/v1/contact`, {
|
|
51
33
|
method: "POST",
|
|
52
|
-
headers: { "Content-Type": "application/json" },
|
|
34
|
+
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
53
35
|
body: JSON.stringify(body),
|
|
54
36
|
});
|
|
55
37
|
const data = await res.json();
|
package/lib/apps.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { findProject, readWallet, loadProjects, saveProjects, API, WALLET_FILE, PROJECTS_FILE } from "./config.mjs";
|
|
1
|
+
import { findProject, loadProjects, saveProjects, API, PROJECTS_FILE, walletAuthHeaders } from "./config.mjs";
|
|
3
2
|
import { mkdirSync, writeFileSync } from "fs";
|
|
4
3
|
|
|
5
4
|
const HELP = `run402 apps — Browse and manage the app marketplace
|
|
@@ -49,31 +48,14 @@ async function fork(versionId, name, args) {
|
|
|
49
48
|
if (args[i] === "--tier" && args[i + 1]) opts.tier = args[++i];
|
|
50
49
|
if (args[i] === "--subdomain" && args[i + 1]) opts.subdomain = args[++i];
|
|
51
50
|
}
|
|
52
|
-
|
|
53
|
-
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
54
|
-
process.exit(1);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const wallet = readWallet();
|
|
58
|
-
const { privateKeyToAccount } = await import("viem/accounts");
|
|
59
|
-
const { createPublicClient, http } = await import("viem");
|
|
60
|
-
const { baseSepolia } = await import("viem/chains");
|
|
61
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
62
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
63
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
64
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
65
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
66
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
67
|
-
const client = new x402Client();
|
|
68
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
69
|
-
const fetchPaid = wrapFetchWithPayment(fetch, client);
|
|
51
|
+
const authHeaders = await walletAuthHeaders();
|
|
70
52
|
|
|
71
53
|
const body = { version_id: versionId, name };
|
|
72
54
|
if (opts.subdomain) body.subdomain = opts.subdomain;
|
|
73
55
|
|
|
74
|
-
const res = await
|
|
56
|
+
const res = await fetch(`${API}/fork/v1`, {
|
|
75
57
|
method: "POST",
|
|
76
|
-
headers: { "Content-Type": "application/json" },
|
|
58
|
+
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
77
59
|
body: JSON.stringify(body),
|
|
78
60
|
});
|
|
79
61
|
const data = await res.json();
|
package/lib/config.mjs
CHANGED
|
@@ -36,6 +36,16 @@ export function saveProjects(projects) {
|
|
|
36
36
|
writeFileSync(PROJECTS_FILE, JSON.stringify(projects, null, 2), { mode: 0o600 });
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
export async function walletAuthHeaders() {
|
|
40
|
+
const w = readWallet();
|
|
41
|
+
if (!w) { console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create" })); process.exit(1); }
|
|
42
|
+
const { privateKeyToAccount } = await import("viem/accounts");
|
|
43
|
+
const account = privateKeyToAccount(w.privateKey);
|
|
44
|
+
const timestamp = Math.floor(Date.now() / 1000).toString();
|
|
45
|
+
const signature = await account.signMessage({ message: `run402:${timestamp}` });
|
|
46
|
+
return { "X-Run402-Wallet": account.address, "X-Run402-Signature": signature, "X-Run402-Timestamp": timestamp };
|
|
47
|
+
}
|
|
48
|
+
|
|
39
49
|
export function findProject(id) {
|
|
40
50
|
const p = loadProjects().find(p => p.project_id === id);
|
|
41
51
|
if (!p) { console.error(`Project ${id} not found in local registry.`); process.exit(1); }
|
package/lib/deploy.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { readFileSync,
|
|
2
|
-
import {
|
|
1
|
+
import { readFileSync, mkdirSync, writeFileSync } from "fs";
|
|
2
|
+
import { loadProjects, API, PROJECTS_FILE, walletAuthHeaders } from "./config.mjs";
|
|
3
3
|
|
|
4
4
|
const HELP = `run402 deploy — Deploy a full-stack app or static site on Run402
|
|
5
5
|
|
|
@@ -8,35 +8,27 @@ Usage:
|
|
|
8
8
|
cat manifest.json | run402 deploy [options]
|
|
9
9
|
|
|
10
10
|
Options:
|
|
11
|
-
--tier <tier> Deployment tier: prototype | hobby | team (default: prototype)
|
|
12
11
|
--manifest <file> Path to manifest JSON file (default: read from stdin)
|
|
13
12
|
--help, -h Show this help message
|
|
14
13
|
|
|
15
|
-
Tiers:
|
|
16
|
-
prototype Smallest, cheapest — great for demos and experiments
|
|
17
|
-
hobby Mid-tier — personal projects and side hustles
|
|
18
|
-
team Full power — production-ready, shared team access
|
|
19
|
-
|
|
20
14
|
Manifest format (JSON):
|
|
21
15
|
{
|
|
22
16
|
"name": "my-app",
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
},
|
|
27
|
-
"env": {
|
|
28
|
-
"MY_VAR": "value"
|
|
29
|
-
}
|
|
17
|
+
"migrations": "CREATE TABLE items ...",
|
|
18
|
+
"site": [{ "file": "index.html", "data": "<html>...</html>" }],
|
|
19
|
+
"subdomain": "my-app"
|
|
30
20
|
}
|
|
31
21
|
|
|
32
22
|
Examples:
|
|
33
|
-
run402 deploy --
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
run402 deploy --manifest app.json
|
|
24
|
+
cat app.json | run402 deploy
|
|
25
|
+
|
|
26
|
+
Prerequisites:
|
|
27
|
+
- run402 init Set up wallet and funding
|
|
28
|
+
- run402 tier set prototype Subscribe to a tier
|
|
36
29
|
|
|
37
30
|
Notes:
|
|
38
|
-
- Requires
|
|
39
|
-
- Payments are processed automatically via x402 micropayments (Base Sepolia USDC)
|
|
31
|
+
- Requires an active tier subscription (run402 tier set <tier>)
|
|
40
32
|
- Project credentials (project_id, keys, URL) are saved locally after deploy
|
|
41
33
|
- Use 'run402 projects list' to see all deployed projects
|
|
42
34
|
`;
|
|
@@ -56,35 +48,16 @@ function saveProject(project) {
|
|
|
56
48
|
}
|
|
57
49
|
|
|
58
50
|
export async function run(args) {
|
|
59
|
-
const opts = {
|
|
51
|
+
const opts = { manifest: null };
|
|
60
52
|
for (let i = 0; i < args.length; i++) {
|
|
61
53
|
if (args[i] === "--help" || args[i] === "-h") { console.log(HELP); process.exit(0); }
|
|
62
|
-
if (args[i] === "--tier" && args[i + 1]) opts.tier = args[++i];
|
|
63
54
|
if (args[i] === "--manifest" && args[i + 1]) opts.manifest = args[++i];
|
|
64
55
|
}
|
|
65
56
|
|
|
66
|
-
if (!existsSync(WALLET_FILE)) {
|
|
67
|
-
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
68
|
-
process.exit(1);
|
|
69
|
-
}
|
|
70
|
-
const wallet = readWallet();
|
|
71
57
|
const manifest = opts.manifest ? JSON.parse(readFileSync(opts.manifest, "utf-8")) : JSON.parse(await readStdin());
|
|
72
58
|
|
|
73
|
-
const
|
|
74
|
-
const {
|
|
75
|
-
const { baseSepolia } = await import("viem/chains");
|
|
76
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
77
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
78
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
79
|
-
|
|
80
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
81
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
82
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
83
|
-
const client = new x402Client();
|
|
84
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
85
|
-
const fetchPaid = wrapFetchWithPayment(fetch, client);
|
|
86
|
-
|
|
87
|
-
const res = await fetchPaid(`${API}/deploy/v1`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(manifest) });
|
|
59
|
+
const authHeaders = await walletAuthHeaders();
|
|
60
|
+
const res = await fetch(`${API}/deploy/v1`, { method: "POST", headers: { "Content-Type": "application/json", ...authHeaders }, body: JSON.stringify(manifest) });
|
|
88
61
|
const result = await res.json();
|
|
89
62
|
if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...result })); process.exit(1); }
|
|
90
63
|
saveProject(result);
|
package/lib/init.mjs
CHANGED
|
@@ -99,7 +99,7 @@ export async function run() {
|
|
|
99
99
|
if (!tierInfo || !tierInfo.tier || tierInfo.status !== "active") {
|
|
100
100
|
console.log(" Next: run402 tier set prototype");
|
|
101
101
|
} else {
|
|
102
|
-
console.log(" Ready to deploy. Run: run402 deploy --
|
|
102
|
+
console.log(" Ready to deploy. Run: run402 deploy --manifest app.json");
|
|
103
103
|
}
|
|
104
104
|
console.log();
|
|
105
105
|
}
|
package/lib/message.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { existsSync } from "fs";
|
|
1
|
+
import { API, walletAuthHeaders } from "./config.mjs";
|
|
3
2
|
|
|
4
3
|
const HELP = `run402 message — Send messages to Run402 developers
|
|
5
4
|
|
|
@@ -16,28 +15,11 @@ Examples:
|
|
|
16
15
|
|
|
17
16
|
async function send(text) {
|
|
18
17
|
if (!text) { console.error(JSON.stringify({ status: "error", message: "Missing message text" })); process.exit(1); }
|
|
19
|
-
|
|
20
|
-
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const wallet = readWallet();
|
|
25
|
-
const { privateKeyToAccount } = await import("viem/accounts");
|
|
26
|
-
const { createPublicClient, http } = await import("viem");
|
|
27
|
-
const { baseSepolia } = await import("viem/chains");
|
|
28
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
29
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
30
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
31
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
32
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
33
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
34
|
-
const client = new x402Client();
|
|
35
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
36
|
-
const fetchPaid = wrapFetchWithPayment(fetch, client);
|
|
18
|
+
const authHeaders = await walletAuthHeaders();
|
|
37
19
|
|
|
38
|
-
const res = await
|
|
20
|
+
const res = await fetch(`${API}/message/v1`, {
|
|
39
21
|
method: "POST",
|
|
40
|
-
headers: { "Content-Type": "application/json" },
|
|
22
|
+
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
41
23
|
body: JSON.stringify({ message: text }),
|
|
42
24
|
});
|
|
43
25
|
const data = await res.json();
|
package/lib/projects.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { findProject, loadProjects, saveProjects,
|
|
2
|
-
import {
|
|
1
|
+
import { findProject, loadProjects, saveProjects, API, PROJECTS_FILE, walletAuthHeaders } from "./config.mjs";
|
|
2
|
+
import { mkdirSync, writeFileSync } from "fs";
|
|
3
3
|
|
|
4
4
|
const HELP = `run402 projects — Manage your deployed Run402 projects
|
|
5
5
|
|
|
@@ -36,26 +36,6 @@ Notes:
|
|
|
36
36
|
- RLS templates: user_owns_rows, public_read, public_read_write
|
|
37
37
|
`;
|
|
38
38
|
|
|
39
|
-
async function setupPaidFetch() {
|
|
40
|
-
if (!existsSync(WALLET_FILE)) {
|
|
41
|
-
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
const wallet = readWallet();
|
|
45
|
-
const { privateKeyToAccount } = await import("viem/accounts");
|
|
46
|
-
const { createPublicClient, http } = await import("viem");
|
|
47
|
-
const { baseSepolia } = await import("viem/chains");
|
|
48
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
49
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
50
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
51
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
52
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
53
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
54
|
-
const client = new x402Client();
|
|
55
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
56
|
-
return wrapFetchWithPayment(fetch, client);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
39
|
async function quote() {
|
|
60
40
|
const res = await fetch(`${API}/tiers/v1`);
|
|
61
41
|
const data = await res.json();
|
|
@@ -69,12 +49,12 @@ async function provision(args) {
|
|
|
69
49
|
if (args[i] === "--tier" && args[i + 1]) opts.tier = args[++i];
|
|
70
50
|
if (args[i] === "--name" && args[i + 1]) opts.name = args[++i];
|
|
71
51
|
}
|
|
72
|
-
const
|
|
52
|
+
const authHeaders = await walletAuthHeaders();
|
|
73
53
|
const body = { tier: opts.tier };
|
|
74
54
|
if (opts.name) body.name = opts.name;
|
|
75
|
-
const res = await
|
|
55
|
+
const res = await fetch(`${API}/projects/v1`, {
|
|
76
56
|
method: "POST",
|
|
77
|
-
headers: { "Content-Type": "application/json" },
|
|
57
|
+
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
78
58
|
body: JSON.stringify(body),
|
|
79
59
|
});
|
|
80
60
|
const data = await res.json();
|
package/lib/sites.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { readFileSync
|
|
2
|
-
import {
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { API, walletAuthHeaders } from "./config.mjs";
|
|
3
3
|
|
|
4
4
|
const HELP = `run402 sites — Deploy and manage static sites
|
|
5
5
|
|
|
@@ -53,33 +53,15 @@ async function deploy(args) {
|
|
|
53
53
|
if (args[i] === "--target" && args[i + 1]) opts.target = args[++i];
|
|
54
54
|
}
|
|
55
55
|
if (!opts.name) { console.error(JSON.stringify({ status: "error", message: "Missing --name <name>" })); process.exit(1); }
|
|
56
|
-
if (!existsSync(WALLET_FILE)) {
|
|
57
|
-
console.error(JSON.stringify({ status: "error", message: "No wallet found. Run: run402 wallet create && run402 wallet fund" }));
|
|
58
|
-
process.exit(1);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
56
|
const manifest = opts.manifest ? JSON.parse(readFileSync(opts.manifest, "utf-8")) : JSON.parse(await readStdin());
|
|
62
57
|
const body = { name: opts.name, files: manifest.files };
|
|
63
58
|
if (opts.project) body.project = opts.project;
|
|
64
59
|
if (opts.target) body.target = opts.target;
|
|
65
60
|
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
const { createPublicClient, http } = await import("viem");
|
|
69
|
-
const { baseSepolia } = await import("viem/chains");
|
|
70
|
-
const { x402Client, wrapFetchWithPayment } = await import("@x402/fetch");
|
|
71
|
-
const { ExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
72
|
-
const { toClientEvmSigner } = await import("@x402/evm");
|
|
73
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
74
|
-
const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });
|
|
75
|
-
const signer = toClientEvmSigner(account, publicClient);
|
|
76
|
-
const client = new x402Client();
|
|
77
|
-
client.register("eip155:84532", new ExactEvmScheme(signer));
|
|
78
|
-
const fetchPaid = wrapFetchWithPayment(fetch, client);
|
|
79
|
-
|
|
80
|
-
const res = await fetchPaid(`${API}/deployments/v1`, {
|
|
61
|
+
const authHeaders = await walletAuthHeaders();
|
|
62
|
+
const res = await fetch(`${API}/deployments/v1`, {
|
|
81
63
|
method: "POST",
|
|
82
|
-
headers: { "Content-Type": "application/json" },
|
|
64
|
+
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
83
65
|
body: JSON.stringify(body),
|
|
84
66
|
});
|
|
85
67
|
const data = await res.json();
|
package/package.json
CHANGED