@mexty/cli 1.3.0 → 1.4.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/BLOCKS_OVERVIEW.md +229 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +9 -7
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/publish.d.ts +5 -1
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +41 -12
- package/dist/commands/publish.js.map +1 -1
- package/dist/index.js +2 -11
- package/dist/index.js.map +1 -1
- package/dist/utils/api.d.ts +11 -0
- package/dist/utils/api.d.ts.map +1 -1
- package/dist/utils/api.js +8 -0
- package/dist/utils/api.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/create.ts +11 -7
- package/src/commands/publish.ts +146 -55
- package/src/index.ts +2 -13
- package/src/utils/api.ts +27 -0
- package/src/commands/fork.ts +0 -58
- package/src/commands/sync.ts +0 -350
package/src/commands/publish.ts
CHANGED
|
@@ -1,49 +1,54 @@
|
|
|
1
|
-
import chalk from
|
|
2
|
-
import fs from
|
|
3
|
-
import path from
|
|
4
|
-
import { apiClient } from
|
|
5
|
-
import { GitManager } from
|
|
6
|
-
import { createInterface } from
|
|
7
|
-
|
|
8
|
-
import { requireAuthentication, getAuthenticatedUser } from
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { apiClient } from "../utils/api";
|
|
5
|
+
import { GitManager } from "../utils/git";
|
|
6
|
+
import { createInterface } from "readline";
|
|
7
|
+
// Removed sync command import as it's been deleted
|
|
8
|
+
import { requireAuthentication, getAuthenticatedUser } from "../utils/auth";
|
|
9
9
|
|
|
10
10
|
// Simple confirmation function
|
|
11
11
|
async function confirm(question: string): Promise<boolean> {
|
|
12
12
|
return new Promise((resolve) => {
|
|
13
13
|
const rl = createInterface({
|
|
14
14
|
input: process.stdin,
|
|
15
|
-
output: process.stdout
|
|
15
|
+
output: process.stdout,
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
rl.question(`${question} (y/N): `, (answer) => {
|
|
19
19
|
rl.close();
|
|
20
|
-
resolve(
|
|
20
|
+
resolve(
|
|
21
|
+
answer.toLowerCase().trim() === "y" ||
|
|
22
|
+
answer.toLowerCase().trim() === "yes"
|
|
23
|
+
);
|
|
21
24
|
});
|
|
22
25
|
});
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
// Extract block ID from package.json or git URL
|
|
26
29
|
async function findBlockId(): Promise<string | null> {
|
|
27
|
-
const packageJsonPath = path.join(process.cwd(),
|
|
28
|
-
|
|
30
|
+
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
31
|
+
|
|
29
32
|
if (fs.existsSync(packageJsonPath)) {
|
|
30
33
|
try {
|
|
31
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath,
|
|
32
|
-
|
|
34
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
35
|
+
|
|
33
36
|
// Look for block ID in package.json name or description
|
|
34
|
-
if (packageJson.name && packageJson.name.startsWith(
|
|
35
|
-
return packageJson.name.replace(
|
|
37
|
+
if (packageJson.name && packageJson.name.startsWith("block-")) {
|
|
38
|
+
return packageJson.name.replace("block-", "");
|
|
36
39
|
}
|
|
37
|
-
|
|
40
|
+
|
|
38
41
|
// Look in description for block ID pattern
|
|
39
42
|
if (packageJson.description) {
|
|
40
|
-
const match = packageJson.description.match(
|
|
43
|
+
const match = packageJson.description.match(
|
|
44
|
+
/block[:\s]+([a-f0-9]{24})/i
|
|
45
|
+
);
|
|
41
46
|
if (match) {
|
|
42
47
|
return match[1];
|
|
43
48
|
}
|
|
44
49
|
}
|
|
45
50
|
} catch (error) {
|
|
46
|
-
console.warn(chalk.yellow(
|
|
51
|
+
console.warn(chalk.yellow("⚠️ Could not parse package.json"));
|
|
47
52
|
}
|
|
48
53
|
}
|
|
49
54
|
|
|
@@ -51,7 +56,7 @@ async function findBlockId(): Promise<string | null> {
|
|
|
51
56
|
try {
|
|
52
57
|
const gitManager = new GitManager();
|
|
53
58
|
const remoteUrl = await gitManager.getRemoteUrl();
|
|
54
|
-
|
|
59
|
+
|
|
55
60
|
if (remoteUrl) {
|
|
56
61
|
const match = remoteUrl.match(/block-([a-f0-9]{24})/);
|
|
57
62
|
if (match) {
|
|
@@ -65,21 +70,36 @@ async function findBlockId(): Promise<string | null> {
|
|
|
65
70
|
return null;
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
|
|
73
|
+
interface PublishOptions {
|
|
74
|
+
agent?: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export async function publishCommand(
|
|
78
|
+
options: PublishOptions = {}
|
|
79
|
+
): Promise<void> {
|
|
69
80
|
try {
|
|
70
81
|
// Check authentication first
|
|
71
82
|
requireAuthentication();
|
|
72
|
-
|
|
83
|
+
|
|
73
84
|
const user = getAuthenticatedUser();
|
|
74
|
-
console.log(chalk.blue(
|
|
75
|
-
console.log(
|
|
85
|
+
console.log(chalk.blue("🚀 Publishing block to marketplace..."));
|
|
86
|
+
console.log(
|
|
87
|
+
chalk.gray(` User: ${user?.fullName || user?.email || "Unknown"}`)
|
|
88
|
+
);
|
|
89
|
+
console.log(
|
|
90
|
+
chalk.gray(` Agent insertable: ${options.agent ? "Yes" : "No"}`)
|
|
91
|
+
);
|
|
76
92
|
|
|
77
93
|
// Check if we're in a git repository
|
|
78
94
|
const gitManager = new GitManager();
|
|
79
95
|
const isGitRepo = await gitManager.isGitRepository();
|
|
80
|
-
|
|
96
|
+
|
|
81
97
|
if (!isGitRepo) {
|
|
82
|
-
console.error(
|
|
98
|
+
console.error(
|
|
99
|
+
chalk.red(
|
|
100
|
+
"❌ Not a git repository. Please run this command from a block repository."
|
|
101
|
+
)
|
|
102
|
+
);
|
|
83
103
|
process.exit(1);
|
|
84
104
|
}
|
|
85
105
|
|
|
@@ -91,8 +111,14 @@ export async function publishCommand(): Promise<void> {
|
|
|
91
111
|
// Find block ID
|
|
92
112
|
const blockId = await findBlockId();
|
|
93
113
|
if (!blockId) {
|
|
94
|
-
console.error(
|
|
95
|
-
|
|
114
|
+
console.error(
|
|
115
|
+
chalk.red("❌ Could not determine block ID from repository.")
|
|
116
|
+
);
|
|
117
|
+
console.error(
|
|
118
|
+
chalk.yellow(
|
|
119
|
+
" Make sure you are in a block repository created with mexty"
|
|
120
|
+
)
|
|
121
|
+
);
|
|
96
122
|
process.exit(1);
|
|
97
123
|
}
|
|
98
124
|
|
|
@@ -100,60 +126,125 @@ export async function publishCommand(): Promise<void> {
|
|
|
100
126
|
|
|
101
127
|
// Check for uncommitted changes
|
|
102
128
|
if (repoInfo.hasChanges) {
|
|
103
|
-
console.log(chalk.yellow(
|
|
104
|
-
console.log(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
129
|
+
console.log(chalk.yellow("⚠️ You have uncommitted changes."));
|
|
130
|
+
console.log(
|
|
131
|
+
chalk.gray(" Please commit your changes before publishing:")
|
|
132
|
+
);
|
|
133
|
+
console.log(
|
|
134
|
+
chalk.gray(' git add . && git commit -m "Your commit message"')
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const proceed = await confirm("Do you want to continue anyway?");
|
|
108
138
|
if (!proceed) {
|
|
109
|
-
console.log(chalk.yellow(
|
|
139
|
+
console.log(chalk.yellow("🚫 Publishing cancelled."));
|
|
110
140
|
return;
|
|
111
141
|
}
|
|
112
142
|
}
|
|
113
143
|
|
|
114
144
|
// Ask user to push changes
|
|
115
|
-
console.log(chalk.blue(
|
|
145
|
+
console.log(chalk.blue("\n📤 Push your changes to GitHub:"));
|
|
116
146
|
console.log(chalk.gray(` git push origin ${repoInfo.branch}`));
|
|
117
|
-
|
|
118
|
-
const pushed = await confirm(
|
|
147
|
+
|
|
148
|
+
const pushed = await confirm("Have you pushed your changes to GitHub?");
|
|
119
149
|
if (!pushed) {
|
|
120
|
-
console.log(
|
|
150
|
+
console.log(
|
|
151
|
+
chalk.yellow(
|
|
152
|
+
"🚫 Please push your changes first and then run publish again."
|
|
153
|
+
)
|
|
154
|
+
);
|
|
121
155
|
return;
|
|
122
156
|
}
|
|
123
157
|
|
|
124
158
|
// Trigger save and bundle
|
|
125
|
-
console.log(chalk.yellow(
|
|
126
|
-
|
|
159
|
+
console.log(chalk.yellow("📡 Triggering build and bundle process..."));
|
|
160
|
+
|
|
127
161
|
try {
|
|
128
162
|
const result = await apiClient.saveAndBundle({ blockId });
|
|
129
|
-
|
|
130
|
-
console.log(chalk.green(
|
|
163
|
+
|
|
164
|
+
console.log(chalk.green("✅ Block bundled successfully!"));
|
|
131
165
|
console.log(chalk.gray(` Bundle Path: ${result.bundlePath}`));
|
|
132
166
|
console.log(chalk.gray(` Federation URL: ${result.federationUrl}`));
|
|
133
|
-
|
|
167
|
+
|
|
134
168
|
if (result.message) {
|
|
135
169
|
console.log(chalk.blue(` ${result.message}`));
|
|
136
170
|
}
|
|
137
171
|
|
|
138
|
-
//
|
|
139
|
-
console.log(chalk.blue(
|
|
172
|
+
// Update sharing scope to publish to marketplace (free only)
|
|
173
|
+
console.log(chalk.blue("\n🌐 Publishing to marketplace..."));
|
|
174
|
+
|
|
140
175
|
try {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
176
|
+
// Get current block to check existing scope
|
|
177
|
+
const block = await apiClient.getBlock(blockId);
|
|
178
|
+
const currentScope = block?.scope || ["user-store"];
|
|
179
|
+
|
|
180
|
+
// Add published-store to scope if not already present
|
|
181
|
+
const newScope = [
|
|
182
|
+
...new Set([...currentScope, "user-store", "published-store"]),
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
await apiClient.updateBlockSharing(blockId, newScope);
|
|
186
|
+
console.log(chalk.green("✅ Block published to marketplace (free)"));
|
|
187
|
+
|
|
188
|
+
// Update agent insertability if requested
|
|
189
|
+
if (options.agent) {
|
|
190
|
+
console.log(chalk.blue("🤖 Making block insertable by AI agents..."));
|
|
191
|
+
try {
|
|
192
|
+
await apiClient.updateBlockAgentInsertable(blockId, true);
|
|
193
|
+
console.log(chalk.green("✅ Block is now insertable by AI agents"));
|
|
194
|
+
} catch (agentError: any) {
|
|
195
|
+
// This might fail if user is not Mext staff, but that's okay
|
|
196
|
+
console.log(
|
|
197
|
+
chalk.yellow(
|
|
198
|
+
"⚠️ Could not set agent insertability (requires Mext staff permissions)"
|
|
199
|
+
)
|
|
200
|
+
);
|
|
201
|
+
console.log(
|
|
202
|
+
chalk.gray(
|
|
203
|
+
` Error: ${agentError.message || "Permission denied"}`
|
|
204
|
+
)
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
} catch (sharingError: any) {
|
|
209
|
+
console.error(
|
|
210
|
+
chalk.red("❌ Failed to publish to marketplace:"),
|
|
211
|
+
sharingError.message
|
|
212
|
+
);
|
|
213
|
+
console.log(
|
|
214
|
+
chalk.yellow(
|
|
215
|
+
" Block was built successfully but not published to marketplace."
|
|
216
|
+
)
|
|
217
|
+
);
|
|
218
|
+
console.log(
|
|
219
|
+
chalk.gray(" You can try publishing again or contact support.")
|
|
220
|
+
);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Success message
|
|
225
|
+
console.log(
|
|
226
|
+
chalk.green("\n🎉 Block published to marketplace successfully!")
|
|
227
|
+
);
|
|
228
|
+
console.log(chalk.blue("Your block is now:"));
|
|
229
|
+
console.log(chalk.gray(" ✓ Available for free download by anyone"));
|
|
230
|
+
console.log(chalk.gray(" ✓ Discoverable in the marketplace"));
|
|
231
|
+
if (options.agent) {
|
|
232
|
+
console.log(
|
|
233
|
+
chalk.gray(" ✓ Insertable by AI agents (if you have permissions)")
|
|
234
|
+
);
|
|
147
235
|
}
|
|
148
|
-
|
|
236
|
+
console.log(
|
|
237
|
+
chalk.gray(
|
|
238
|
+
` ✓ Viewable at: https://mexty.ai/preview.html?blockId=${blockId}`
|
|
239
|
+
)
|
|
240
|
+
);
|
|
149
241
|
} catch (buildError: any) {
|
|
150
242
|
console.error(chalk.red(`❌ Build failed: ${buildError.message}`));
|
|
151
|
-
console.log(chalk.yellow(
|
|
243
|
+
console.log(chalk.yellow(" Check the server logs for more details."));
|
|
152
244
|
process.exit(1);
|
|
153
245
|
}
|
|
154
|
-
|
|
155
246
|
} catch (error: any) {
|
|
156
247
|
console.error(chalk.red(`❌ Failed to publish block: ${error.message}`));
|
|
157
248
|
process.exit(1);
|
|
158
249
|
}
|
|
159
|
-
}
|
|
250
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -4,10 +4,8 @@ import { Command } from "commander";
|
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import { loginCommand } from "./commands/login";
|
|
6
6
|
import { createCommand } from "./commands/create";
|
|
7
|
-
import { forkCommand } from "./commands/fork";
|
|
8
7
|
import { deleteCommand } from "./commands/delete";
|
|
9
8
|
import { publishCommand } from "./commands/publish";
|
|
10
|
-
import { syncCommand } from "./commands/sync";
|
|
11
9
|
import { saveCommand } from "./commands/save";
|
|
12
10
|
import { apiClient } from "./utils/api";
|
|
13
11
|
|
|
@@ -57,11 +55,6 @@ program
|
|
|
57
55
|
)
|
|
58
56
|
.action(createCommand);
|
|
59
57
|
|
|
60
|
-
program
|
|
61
|
-
.command("fork <blockId>")
|
|
62
|
-
.description("Fork an existing block and clone its repository")
|
|
63
|
-
.action(forkCommand);
|
|
64
|
-
|
|
65
58
|
program
|
|
66
59
|
.command("delete <blockId>")
|
|
67
60
|
.description("Delete a block (requires ownership)")
|
|
@@ -69,14 +62,10 @@ program
|
|
|
69
62
|
|
|
70
63
|
program
|
|
71
64
|
.command("publish")
|
|
72
|
-
.description("Publish current block
|
|
65
|
+
.description("Publish current block to marketplace (free only)")
|
|
66
|
+
.option("--agent", "Make block insertable by AI agents", false)
|
|
73
67
|
.action(publishCommand);
|
|
74
68
|
|
|
75
|
-
program
|
|
76
|
-
.command("sync")
|
|
77
|
-
.description("Sync block registry and update typed exports")
|
|
78
|
-
.action(syncCommand);
|
|
79
|
-
|
|
80
69
|
program
|
|
81
70
|
.command("save")
|
|
82
71
|
.description("Save current block (git add, commit, push, and trigger build)")
|
package/src/utils/api.ts
CHANGED
|
@@ -6,7 +6,16 @@ import os from "os";
|
|
|
6
6
|
|
|
7
7
|
export interface Block {
|
|
8
8
|
_id: string;
|
|
9
|
+
id?: string;
|
|
9
10
|
blockType: string;
|
|
11
|
+
_doc?: {
|
|
12
|
+
_id: string;
|
|
13
|
+
blockType: string;
|
|
14
|
+
title: string;
|
|
15
|
+
description: string;
|
|
16
|
+
gitUrl?: string;
|
|
17
|
+
[key: string]: any;
|
|
18
|
+
};
|
|
10
19
|
title: string;
|
|
11
20
|
description: string;
|
|
12
21
|
gitUrl?: string;
|
|
@@ -225,6 +234,24 @@ class ApiClient {
|
|
|
225
234
|
return response.data;
|
|
226
235
|
}
|
|
227
236
|
|
|
237
|
+
async updateBlockSharing(blockId: string, scope: string[]): Promise<any> {
|
|
238
|
+
const response = await this.client.patch(`/api/blocks/${blockId}/sharing`, {
|
|
239
|
+
scope,
|
|
240
|
+
});
|
|
241
|
+
return response.data;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async updateBlockAgentInsertable(
|
|
245
|
+
blockId: string,
|
|
246
|
+
isInsertableByAgent: boolean
|
|
247
|
+
): Promise<any> {
|
|
248
|
+
const response = await this.client.patch(
|
|
249
|
+
`/api/blocks/${blockId}/agent-insertable`,
|
|
250
|
+
{ isInsertableByAgent }
|
|
251
|
+
);
|
|
252
|
+
return response.data;
|
|
253
|
+
}
|
|
254
|
+
|
|
228
255
|
async healthCheck(): Promise<boolean> {
|
|
229
256
|
try {
|
|
230
257
|
await this.client.get("/api/health");
|
package/src/commands/fork.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { apiClient } from '../utils/api';
|
|
4
|
-
import { GitManager } from '../utils/git';
|
|
5
|
-
import { requireAuthentication, getAuthenticatedUser } from '../utils/auth';
|
|
6
|
-
|
|
7
|
-
export async function forkCommand(blockId: string): Promise<void> {
|
|
8
|
-
try {
|
|
9
|
-
// Check authentication first
|
|
10
|
-
requireAuthentication();
|
|
11
|
-
|
|
12
|
-
const user = getAuthenticatedUser();
|
|
13
|
-
console.log(chalk.blue(`🍴 Forking block: ${blockId}`));
|
|
14
|
-
console.log(chalk.gray(` User: ${user?.fullName || user?.email || 'Unknown'}`));
|
|
15
|
-
|
|
16
|
-
// Fork the block
|
|
17
|
-
console.log(chalk.yellow('📡 Forking block on server...'));
|
|
18
|
-
const forkedBlock = await apiClient.forkBlock({ blockId });
|
|
19
|
-
|
|
20
|
-
console.log(chalk.green(`✅ Block forked successfully!`));
|
|
21
|
-
console.log(chalk.gray(` New Block ID: ${forkedBlock._id}`));
|
|
22
|
-
console.log(chalk.gray(` Title: ${forkedBlock.title}`));
|
|
23
|
-
console.log(chalk.gray(` Description: ${forkedBlock.description}`));
|
|
24
|
-
|
|
25
|
-
if (forkedBlock.gitUrl) {
|
|
26
|
-
console.log(chalk.gray(` GitHub URL: ${forkedBlock.gitUrl}`));
|
|
27
|
-
|
|
28
|
-
// Clone the forked repository
|
|
29
|
-
const repoName = GitManager.extractRepoName(forkedBlock.gitUrl);
|
|
30
|
-
const targetDir = path.join(process.cwd(), repoName);
|
|
31
|
-
|
|
32
|
-
console.log(chalk.yellow(`📦 Cloning forked repository to ./${repoName}...`));
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
const gitManager = new GitManager();
|
|
36
|
-
await gitManager.cloneRepository(forkedBlock.gitUrl, targetDir);
|
|
37
|
-
|
|
38
|
-
console.log(chalk.green(`🎉 Block forked and repository cloned successfully!`));
|
|
39
|
-
console.log(chalk.blue(`\nNext steps:`));
|
|
40
|
-
console.log(chalk.gray(` 1. cd ${repoName}`));
|
|
41
|
-
console.log(chalk.gray(` 2. Make your changes`));
|
|
42
|
-
console.log(chalk.gray(` 3. git add . && git commit -m "Your changes"`));
|
|
43
|
-
console.log(chalk.gray(` 4. mexty publish`));
|
|
44
|
-
|
|
45
|
-
} catch (cloneError: any) {
|
|
46
|
-
console.error(chalk.red(`❌ Failed to clone repository: ${cloneError.message}`));
|
|
47
|
-
console.log(chalk.yellow(`You can manually clone it later:`));
|
|
48
|
-
console.log(chalk.gray(` git clone ${forkedBlock.gitUrl}`));
|
|
49
|
-
}
|
|
50
|
-
} else {
|
|
51
|
-
console.log(chalk.yellow('⚠️ No GitHub repository available for this block'));
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
} catch (error: any) {
|
|
55
|
-
console.error(chalk.red(`❌ Failed to fork block: ${error.message}`));
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
58
|
-
}
|