@mexty/cli 1.4.0 → 1.4.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.
- package/BLOCKS_OVERVIEW.md +262 -0
- package/package.json +1 -1
- package/src/commands/create.ts +14 -0
- package/src/utils/api.ts +11 -0
package/BLOCKS_OVERVIEW.md
CHANGED
|
@@ -226,4 +226,266 @@ Blocks can be marked as "insertable by agent" which allows AI systems to:
|
|
|
226
226
|
4. Commit and publish with `mexty save`
|
|
227
227
|
5. Share or publish to marketplace
|
|
228
228
|
|
|
229
|
+
## CLI Commands
|
|
230
|
+
|
|
231
|
+
The MEXTY CLI provides a complete toolkit for block development and publishing:
|
|
232
|
+
|
|
233
|
+
### Installation
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
npm install -g @mexty/cli
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Authentication
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
mexty login
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Authenticate with your MEXTY account to access all CLI features.
|
|
246
|
+
|
|
247
|
+
### Block Creation
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
mexty create block --name "Block Name" --description "Description" --category "category"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
- Creates a new block via the API
|
|
254
|
+
- Automatically generates a GitHub repository
|
|
255
|
+
- Clones the repository locally
|
|
256
|
+
- Changes to the block directory
|
|
257
|
+
- Sets up the development environment
|
|
258
|
+
|
|
259
|
+
**Example:**
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
mexty create block --name "Weather Widget" --description "A beautiful weather display component" --category "widget"
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Development & Saving
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
mexty save
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
- Stages all changes (`git add .`)
|
|
272
|
+
- Prompts for commit message
|
|
273
|
+
- Commits changes to git
|
|
274
|
+
- Pushes to GitHub
|
|
275
|
+
- Triggers the save-and-bundle process to build the block
|
|
276
|
+
|
|
277
|
+
### Publishing to Marketplace
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
mexty publish [--agent]
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
- Builds and bundles the block
|
|
284
|
+
- Publishes to the marketplace (free only via CLI)
|
|
285
|
+
- Makes block discoverable by all users
|
|
286
|
+
- Optional `--agent` flag makes block insertable by AI agents (requires Mext staff permissions)
|
|
287
|
+
|
|
288
|
+
**Example:**
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
mexty publish --agent
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Block Management
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
mexty delete <blockId>
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Deletes a block (requires ownership).
|
|
301
|
+
|
|
302
|
+
### Command Workflow
|
|
303
|
+
|
|
304
|
+
1. **Create a new block:**
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
mexty create block --name "My Widget" --description "An awesome widget" --category "utility"
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
2. **Develop your block:**
|
|
311
|
+
|
|
312
|
+
- Edit `src/block.tsx` to implement your component
|
|
313
|
+
- Define TypeScript interfaces for props
|
|
314
|
+
- Test locally with `npm start`
|
|
315
|
+
|
|
316
|
+
3. **Save your progress:**
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
mexty save
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
4. **Publish to marketplace:**
|
|
323
|
+
```bash
|
|
324
|
+
mexty publish --agent
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### CLI Features
|
|
328
|
+
|
|
329
|
+
- **Automatic GitHub Integration**: Creates and manages repositories
|
|
330
|
+
- **TypeScript Support**: Full TypeScript development environment
|
|
331
|
+
- **Props Schema Detection**: Automatically generates props schema from TypeScript interfaces
|
|
332
|
+
- **Federation Bundling**: Creates optimized bundles for embedding
|
|
333
|
+
- **Marketplace Publishing**: One-command publishing to the marketplace
|
|
334
|
+
- **AI Agent Integration**: Optional agent insertability for automated content creation
|
|
335
|
+
|
|
229
336
|
This system enables rapid creation of interactive content while maintaining consistency, reusability, and ease of customization for end users.
|
|
337
|
+
|
|
338
|
+
# @mexty/realtime
|
|
339
|
+
|
|
340
|
+
React hooks for real-time collaborative features using Yjs and Hocuspocus.
|
|
341
|
+
|
|
342
|
+
## Installation
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
npm install @mexty/realtime
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## Usage
|
|
349
|
+
|
|
350
|
+
```tsx
|
|
351
|
+
import { useCollabSpace } from "@mexty/realtime";
|
|
352
|
+
|
|
353
|
+
// 🧠 Example 1: Collaborative JSON document editor
|
|
354
|
+
export function DocumentEditor({ blockId }: { blockId: string }) {
|
|
355
|
+
const { state, update } = useCollabSpace(`block:${blockId}`, {
|
|
356
|
+
document: {
|
|
357
|
+
title: "Untitled",
|
|
358
|
+
content: "Write something...",
|
|
359
|
+
},
|
|
360
|
+
game: { weights: [] },
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
// ✅ Partial update usage
|
|
364
|
+
const handleTitleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
365
|
+
update({ document: { ...state.document, title: e.target.value } });
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
// ✅ Functional update usage
|
|
369
|
+
const resetContent = () => {
|
|
370
|
+
update((prev) => ({
|
|
371
|
+
...prev,
|
|
372
|
+
document: { ...prev.document, content: "" },
|
|
373
|
+
}));
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
return (
|
|
377
|
+
<div className="p-4 border rounded space-y-3">
|
|
378
|
+
<h2 className="text-lg font-bold">Collaborative Document</h2>
|
|
379
|
+
<input
|
|
380
|
+
type="text"
|
|
381
|
+
className="border p-2 w-full"
|
|
382
|
+
value={state.document.title}
|
|
383
|
+
onChange={handleTitleChange}
|
|
384
|
+
/>
|
|
385
|
+
<textarea
|
|
386
|
+
className="border p-2 w-full h-32"
|
|
387
|
+
value={state.document.content}
|
|
388
|
+
onChange={(e) =>
|
|
389
|
+
update({ document: { ...state.document, content: e.target.value } })
|
|
390
|
+
}
|
|
391
|
+
/>
|
|
392
|
+
<button
|
|
393
|
+
onClick={resetContent}
|
|
394
|
+
className="bg-blue-500 text-white px-3 py-1 rounded"
|
|
395
|
+
>
|
|
396
|
+
Reset Content
|
|
397
|
+
</button>
|
|
398
|
+
</div>
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// 🧩 Example 2: Multiplayer tower game state
|
|
403
|
+
export function TowerGame({ blockId }: { blockId: string }) {
|
|
404
|
+
const { state, update } = useCollabSpace(`block:${blockId}`, {
|
|
405
|
+
document: {},
|
|
406
|
+
game: { weights: [] as { team: string; pos: number }[] },
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// ✅ Append new weight (functional update)
|
|
410
|
+
const addWeight = (team: string) => {
|
|
411
|
+
update((prev) => ({
|
|
412
|
+
...prev,
|
|
413
|
+
game: {
|
|
414
|
+
...prev.game,
|
|
415
|
+
weights: [...prev.game.weights, { team, pos: Math.random() * 100 }],
|
|
416
|
+
},
|
|
417
|
+
}));
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
// ✅ Clear game state (partial update)
|
|
421
|
+
const resetGame = () => {
|
|
422
|
+
update({ game: { weights: [] } });
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
return (
|
|
426
|
+
<div className="p-4 border rounded space-y-3">
|
|
427
|
+
<h2 className="text-lg font-bold">Tower Game</h2>
|
|
428
|
+
<button
|
|
429
|
+
onClick={() => addWeight("blue")}
|
|
430
|
+
className="bg-blue-600 text-white px-3 py-1 rounded"
|
|
431
|
+
>
|
|
432
|
+
Add Blue Weight
|
|
433
|
+
</button>
|
|
434
|
+
<button
|
|
435
|
+
onClick={() => addWeight("red")}
|
|
436
|
+
className="bg-red-600 text-white px-3 py-1 rounded"
|
|
437
|
+
>
|
|
438
|
+
Add Red Weight
|
|
439
|
+
</button>
|
|
440
|
+
<button
|
|
441
|
+
onClick={resetGame}
|
|
442
|
+
className="bg-gray-600 text-white px-3 py-1 rounded"
|
|
443
|
+
>
|
|
444
|
+
Reset Game
|
|
445
|
+
</button>
|
|
446
|
+
|
|
447
|
+
<pre className="bg-gray-100 p-2 text-sm rounded overflow-auto">
|
|
448
|
+
{JSON.stringify(state.game, null, 2)}
|
|
449
|
+
</pre>
|
|
450
|
+
</div>
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
## API
|
|
456
|
+
|
|
457
|
+
### `useCollabSpace(documentName, initialState, options?)`
|
|
458
|
+
|
|
459
|
+
#### Parameters
|
|
460
|
+
|
|
461
|
+
- `documentName: string` - Unique identifier for the collaborative document
|
|
462
|
+
- `initialState: T` - Initial state object for the collaborative space
|
|
463
|
+
- `options?: CollabSpaceOptions` - Optional configuration
|
|
464
|
+
|
|
465
|
+
#### Returns
|
|
466
|
+
|
|
467
|
+
- `state: T` - Current collaborative state
|
|
468
|
+
- `update: (updateFn: UpdateFunction<T>) => void` - Function to update state
|
|
469
|
+
- `isConnected: boolean` - WebSocket connection status
|
|
470
|
+
- `connectionStatus: 'connecting' | 'connected' | 'disconnected' | 'error'` - Detailed connection status
|
|
471
|
+
- `userId: string` - Anonymous user ID (persisted in localStorage)
|
|
472
|
+
|
|
473
|
+
#### Options
|
|
474
|
+
|
|
475
|
+
```tsx
|
|
476
|
+
interface CollabSpaceOptions {
|
|
477
|
+
websocketUrl?: string;
|
|
478
|
+
onConnect?: () => void;
|
|
479
|
+
onDisconnect?: () => void;
|
|
480
|
+
onError?: (error: Error) => void;
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
## Features
|
|
485
|
+
|
|
486
|
+
- 🔄 Real-time collaborative state synchronization
|
|
487
|
+
- 🆔 Anonymous user authentication with persistent IDs
|
|
488
|
+
- 🔗 Automatic WebSocket connection management
|
|
489
|
+
- 📱 React hooks for easy integration
|
|
490
|
+
- 🎯 TypeScript support with full type safety
|
|
491
|
+
- 🏗️ Built on Yjs and Hocuspocus for reliability
|
package/package.json
CHANGED
package/src/commands/create.ts
CHANGED
|
@@ -113,6 +113,20 @@ export async function createCommand(
|
|
|
113
113
|
chalk.gray(` Block Type: ${block.blockType || block._doc?.blockType}`)
|
|
114
114
|
);
|
|
115
115
|
|
|
116
|
+
// Add the block to user's structure
|
|
117
|
+
console.log(chalk.yellow("📚 Adding block to your library..."));
|
|
118
|
+
try {
|
|
119
|
+
await apiClient.addBlockToStructure(block.id || block._id);
|
|
120
|
+
console.log(chalk.green(`✅ Block added to your library!`));
|
|
121
|
+
} catch (structureError: any) {
|
|
122
|
+
console.warn(
|
|
123
|
+
chalk.yellow(
|
|
124
|
+
`⚠️ Block created but couldn't add to library: ${structureError.message}`
|
|
125
|
+
)
|
|
126
|
+
);
|
|
127
|
+
console.log(chalk.gray(" The block is still accessible via the API"));
|
|
128
|
+
}
|
|
129
|
+
|
|
116
130
|
// Handle both plain objects and Mongoose documents
|
|
117
131
|
const gitUrl = block.gitUrl || block._doc?.gitUrl;
|
|
118
132
|
if (gitUrl) {
|
package/src/utils/api.ts
CHANGED
|
@@ -283,6 +283,17 @@ class ApiClient {
|
|
|
283
283
|
return data;
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
+
async addBlockToStructure(
|
|
287
|
+
blockId: string,
|
|
288
|
+
parentPath?: string
|
|
289
|
+
): Promise<any> {
|
|
290
|
+
const response = await this.client.post("/api/structure/add-block", {
|
|
291
|
+
blockId,
|
|
292
|
+
parentPath: parentPath || "/",
|
|
293
|
+
});
|
|
294
|
+
return response.data;
|
|
295
|
+
}
|
|
296
|
+
|
|
286
297
|
async logout(): Promise<void> {
|
|
287
298
|
try {
|
|
288
299
|
await this.client.post("/api/auth/logout");
|