@marsengine/mars-client 1.0.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 +61 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +68 -0
- package/package.json +20 -0
- package/src/index.ts +77 -0
- package/tsconfig.json +12 -0
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# @yakreentechnologies/mars-client
|
|
2
|
+
|
|
3
|
+
The official client for the **MARS Engine** - The Enterprise-Grade WebContainer Replacement.
|
|
4
|
+
|
|
5
|
+
This lightweight library allows you to connect to a hosted MARS Engine runtime and control a full Node.js environment directly from the browser.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
* 🚀 **Zero-Copy I/O**: Blazing fast communication with the engine.
|
|
10
|
+
* 🔒 **Secure Sandbox**: Runs code in a hidden, isolated iframe.
|
|
11
|
+
* 📦 **Drop-in Replacement**: API compatible with WebContainer.
|
|
12
|
+
* ⚡ **Vibe Coding Ready**: Optimized for AI-driven development.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @marsengine/mars-client
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### 1. Boot the Engine
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { MarsEngineMessenger } from '@marsengine/mars-client';
|
|
26
|
+
|
|
27
|
+
// Initialize the engine (pointing to your hosted runtime)
|
|
28
|
+
const engine = new MarsEngineMessenger('https://engine.yourdomain.com');
|
|
29
|
+
|
|
30
|
+
await engine.boot();
|
|
31
|
+
console.log('MARS Engine is ready! 🚀');
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 2. Run a Command
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
// Run 'npm install' inside the browser
|
|
38
|
+
const process = await engine.spawn('npm', ['install']);
|
|
39
|
+
|
|
40
|
+
// Stream the output to your terminal
|
|
41
|
+
process.output.pipeTo(new WritableStream({
|
|
42
|
+
write(chunk) {
|
|
43
|
+
console.log(chunk);
|
|
44
|
+
}
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
await process.exit;
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 3. Write a File
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
await engine.fs.writeFile('/src/App.tsx', `
|
|
54
|
+
import React from 'react';
|
|
55
|
+
export default () => <h1>Hello from MARS! 🪐</h1>;
|
|
56
|
+
`);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## License
|
|
60
|
+
|
|
61
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MARS Messenger (Public API)
|
|
3
|
+
* This is the lightweight "Messenger" library that customers install.
|
|
4
|
+
* It contains NO engine logic, only a bridge to the hosted runtime.
|
|
5
|
+
*/
|
|
6
|
+
export declare class MarsEngineMessenger {
|
|
7
|
+
private runtimeUrl;
|
|
8
|
+
private iframe;
|
|
9
|
+
private channel;
|
|
10
|
+
private port;
|
|
11
|
+
constructor(runtimeUrl?: string);
|
|
12
|
+
/**
|
|
13
|
+
* Boot the engine by creating a hidden iframe to the hosted runtime.
|
|
14
|
+
*/
|
|
15
|
+
boot(): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Proxy call to the hosted engine.
|
|
18
|
+
*/
|
|
19
|
+
call(method: string, args: any[]): Promise<any>;
|
|
20
|
+
spawn(command: string, args: string[]): Promise<any>;
|
|
21
|
+
get fs(): {
|
|
22
|
+
writeFile: (path: string, content: any) => Promise<any>;
|
|
23
|
+
readFile: (path: string) => Promise<any>;
|
|
24
|
+
};
|
|
25
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MARS Messenger (Public API)
|
|
4
|
+
* This is the lightweight "Messenger" library that customers install.
|
|
5
|
+
* It contains NO engine logic, only a bridge to the hosted runtime.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.MarsEngineMessenger = void 0;
|
|
9
|
+
class MarsEngineMessenger {
|
|
10
|
+
constructor(runtimeUrl = 'https://runtime.mars.ai') {
|
|
11
|
+
this.runtimeUrl = runtimeUrl;
|
|
12
|
+
this.iframe = null;
|
|
13
|
+
this.port = null;
|
|
14
|
+
this.channel = new MessageChannel();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Boot the engine by creating a hidden iframe to the hosted runtime.
|
|
18
|
+
*/
|
|
19
|
+
async boot() {
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
this.iframe = document.createElement('iframe');
|
|
22
|
+
this.iframe.src = this.runtimeUrl;
|
|
23
|
+
this.iframe.style.display = 'none';
|
|
24
|
+
this.iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
|
|
25
|
+
this.iframe.onload = () => {
|
|
26
|
+
// Handshake: Send our MessagePort to the hosted runtime
|
|
27
|
+
this.iframe.contentWindow.postMessage({ type: 'MARS_HANDSHAKE' }, this.runtimeUrl, [this.channel.port2]);
|
|
28
|
+
this.port = this.channel.port1;
|
|
29
|
+
this.port.onmessage = (event) => {
|
|
30
|
+
if (event.data.type === 'MARS_READY')
|
|
31
|
+
resolve();
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
this.iframe.onerror = reject;
|
|
35
|
+
document.body.appendChild(this.iframe);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Proxy call to the hosted engine.
|
|
40
|
+
*/
|
|
41
|
+
async call(method, args) {
|
|
42
|
+
if (!this.port)
|
|
43
|
+
throw new Error('Engine not booted');
|
|
44
|
+
const requestId = Math.random().toString(36).substring(7);
|
|
45
|
+
this.port.postMessage({ type: 'MARS_CALL', requestId, method, args });
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
const handler = (event) => {
|
|
48
|
+
if (event.data.requestId === requestId) {
|
|
49
|
+
this.port.removeEventListener('message', handler);
|
|
50
|
+
resolve(event.data.result);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
this.port.addEventListener('message', handler);
|
|
54
|
+
this.port.start();
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
// Public API Proxies
|
|
58
|
+
async spawn(command, args) {
|
|
59
|
+
return this.call('spawn', [command, args]);
|
|
60
|
+
}
|
|
61
|
+
get fs() {
|
|
62
|
+
return {
|
|
63
|
+
writeFile: (path, content) => this.call('fs.writeFile', [path, content]),
|
|
64
|
+
readFile: (path) => this.call('fs.readFile', [path]),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.MarsEngineMessenger = MarsEngineMessenger;
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@marsengine/mars-client",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Public Client for MARS Engine (WebContainer Replacement)",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"mars",
|
|
12
|
+
"webcontainer",
|
|
13
|
+
"client"
|
|
14
|
+
],
|
|
15
|
+
"author": "MARS Team",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"typescript": "^5.3.3"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MARS Messenger (Public API)
|
|
3
|
+
* This is the lightweight "Messenger" library that customers install.
|
|
4
|
+
* It contains NO engine logic, only a bridge to the hosted runtime.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export class MarsEngineMessenger {
|
|
8
|
+
private iframe: HTMLIFrameElement | null = null;
|
|
9
|
+
private channel: MessageChannel;
|
|
10
|
+
private port: MessagePort | null = null;
|
|
11
|
+
|
|
12
|
+
constructor(private runtimeUrl: string = 'https://runtime.mars.ai') {
|
|
13
|
+
this.channel = new MessageChannel();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Boot the engine by creating a hidden iframe to the hosted runtime.
|
|
18
|
+
*/
|
|
19
|
+
async boot(): Promise<void> {
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
this.iframe = document.createElement('iframe');
|
|
22
|
+
this.iframe.src = this.runtimeUrl;
|
|
23
|
+
this.iframe.style.display = 'none';
|
|
24
|
+
this.iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
|
|
25
|
+
|
|
26
|
+
this.iframe.onload = () => {
|
|
27
|
+
// Handshake: Send our MessagePort to the hosted runtime
|
|
28
|
+
this.iframe!.contentWindow!.postMessage(
|
|
29
|
+
{ type: 'MARS_HANDSHAKE' },
|
|
30
|
+
this.runtimeUrl,
|
|
31
|
+
[this.channel.port2]
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
this.port = this.channel.port1;
|
|
35
|
+
this.port.onmessage = (event) => {
|
|
36
|
+
if (event.data.type === 'MARS_READY') resolve();
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
this.iframe.onerror = reject;
|
|
41
|
+
document.body.appendChild(this.iframe);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Proxy call to the hosted engine.
|
|
47
|
+
*/
|
|
48
|
+
async call(method: string, args: any[]): Promise<any> {
|
|
49
|
+
if (!this.port) throw new Error('Engine not booted');
|
|
50
|
+
|
|
51
|
+
const requestId = Math.random().toString(36).substring(7);
|
|
52
|
+
this.port.postMessage({ type: 'MARS_CALL', requestId, method, args });
|
|
53
|
+
|
|
54
|
+
return new Promise((resolve) => {
|
|
55
|
+
const handler = (event: MessageEvent) => {
|
|
56
|
+
if (event.data.requestId === requestId) {
|
|
57
|
+
this.port!.removeEventListener('message', handler);
|
|
58
|
+
resolve(event.data.result);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
this.port!.addEventListener('message', handler);
|
|
62
|
+
this.port!.start();
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Public API Proxies
|
|
67
|
+
async spawn(command: string, args: string[]) {
|
|
68
|
+
return this.call('spawn', [command, args]);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
get fs() {
|
|
72
|
+
return {
|
|
73
|
+
writeFile: (path: string, content: any) => this.call('fs.writeFile', [path, content]),
|
|
74
|
+
readFile: (path: string) => this.call('fs.readFile', [path]),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|