@aurorah/wmcp 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 +71 -0
- package/dist/core/client.d.ts +45 -0
- package/dist/core/client.d.ts.map +1 -0
- package/dist/core/client.js +122 -0
- package/dist/core/client.js.map +1 -0
- package/dist/core/errors.d.ts +24 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +40 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/host.d.ts +49 -0
- package/dist/core/host.d.ts.map +1 -0
- package/dist/core/host.js +118 -0
- package/dist/core/host.js.map +1 -0
- package/dist/core/index.d.ts +11 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +10 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/types.d.ts +120 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +6 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/validator.d.ts +12 -0
- package/dist/core/validator.d.ts.map +1 -0
- package/dist/core/validator.js +77 -0
- package/dist/core/validator.js.map +1 -0
- package/dist/utils/stream.d.ts +15 -0
- package/dist/utils/stream.d.ts.map +1 -0
- package/dist/utils/stream.js +67 -0
- package/dist/utils/stream.js.map +1 -0
- package/package.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# wMCP — Web Module Connection Protocol
|
|
2
|
+
|
|
3
|
+
wMCP is a standardized protocol for connecting encapsulated web UI modules to host applications. Inspired by the Model Context Protocol (MCP) for AI/LLM tool integration, wMCP applies the same manifest-driven, capability-based architecture to the web frontend domain — enabling framework-agnostic modules to be plugged into host applications with clear security boundaries and AI-friendly integration patterns.
|
|
4
|
+
|
|
5
|
+
**Status:** Prototype / Proof of Concept
|
|
6
|
+
|
|
7
|
+
## Quick links
|
|
8
|
+
|
|
9
|
+
| Document | Description |
|
|
10
|
+
| -------------------------------------------------- | ------------------ |
|
|
11
|
+
| [docs/CONCEPTS.md](docs/CONCEPTS.md) | Core Concepts |
|
|
12
|
+
| [docs/SPECIFICATION.md](docs/SPECIFICATION.md) | Full Specification |
|
|
13
|
+
| [docs/MCP-COMPARISON.md](docs/MCP-COMPARISON.md) | MCP Comparison |
|
|
14
|
+
| [docs/GETTING-STARTED.md](docs/GETTING-STARTED.md) | Getting Started |
|
|
15
|
+
|
|
16
|
+
## Project structure
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
wmcp-prototype/
|
|
20
|
+
├── docs/ # Specification and guides
|
|
21
|
+
├── examples/ # Runnable example modules and hosts
|
|
22
|
+
│ ├── counter/
|
|
23
|
+
│ ├── rich-text-editor/
|
|
24
|
+
│ ├── analytics-dashboard/
|
|
25
|
+
│ ├── file-manager/
|
|
26
|
+
│ ├── kanban-board/
|
|
27
|
+
│ └── media-player/
|
|
28
|
+
├── src/ # Core protocol implementation (if present)
|
|
29
|
+
└── package.json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick start
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx tsx examples/counter/host-app.ts
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
In another terminal:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npx tsx examples/counter/mock-server.ts
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
HTTP transport:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npx tsx examples/counter/host-app.ts --http
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Examples
|
|
55
|
+
|
|
56
|
+
| Example | Description |
|
|
57
|
+
| --------------------- | -------------------------------------------------------- |
|
|
58
|
+
| `counter` | Minimal getting-started |
|
|
59
|
+
| `rich-text-editor` | Content CRUD, autosave, export |
|
|
60
|
+
| `analytics-dashboard` | Queries, aggregation, live data streams |
|
|
61
|
+
| `file-manager` | File CRUD, upload/download, tree navigation |
|
|
62
|
+
| `kanban-board` | Task management, drag-and-drop, real-time sync |
|
|
63
|
+
| `media-player` | Playlist management, streaming playback, progress events |
|
|
64
|
+
|
|
65
|
+
## Core concepts
|
|
66
|
+
|
|
67
|
+
wMCP is organized around **manifests** (module discovery and metadata), **capabilities** (what a module can do), **events** (host ↔ module messaging), **config** (host-supplied settings), and **hints** (optional UX or integration guidance). See [docs/CONCEPTS.md](docs/CONCEPTS.md) for full detail.
|
|
68
|
+
|
|
69
|
+
## License
|
|
70
|
+
|
|
71
|
+
MIT
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wMCP — Web Module Connection Protocol
|
|
3
|
+
* WmcpClient — used inside the sub-module to call capabilities and emit events.
|
|
4
|
+
*/
|
|
5
|
+
import type { WmcpManifest, CapabilityHandler, EventCallback } from './types.js';
|
|
6
|
+
export declare class WmcpClient {
|
|
7
|
+
readonly manifest: WmcpManifest;
|
|
8
|
+
private handlers;
|
|
9
|
+
private eventListeners;
|
|
10
|
+
private bound;
|
|
11
|
+
constructor(manifest: WmcpManifest);
|
|
12
|
+
/**
|
|
13
|
+
* Called by the host at mount time.
|
|
14
|
+
* Binds handler functions to each capability declared in the manifest.
|
|
15
|
+
* Throws WmcpBindError if a required capability is missing.
|
|
16
|
+
*/
|
|
17
|
+
_bind(handlers: Record<string, CapabilityHandler>): void;
|
|
18
|
+
/**
|
|
19
|
+
* Invokes a request-mode capability.
|
|
20
|
+
*/
|
|
21
|
+
call<T = unknown>(capability: string, params?: Record<string, unknown>): Promise<T>;
|
|
22
|
+
/**
|
|
23
|
+
* Invokes a stream-mode capability, returning an async generator.
|
|
24
|
+
*/
|
|
25
|
+
stream<T = unknown>(capability: string, params?: Record<string, unknown>): AsyncGenerator<T>;
|
|
26
|
+
/**
|
|
27
|
+
* Checks if a capability has been bound (useful for optional capabilities).
|
|
28
|
+
*/
|
|
29
|
+
has(capability: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Sub-module calls this to emit an event to the host.
|
|
32
|
+
*/
|
|
33
|
+
emit(event: string, data: unknown): void;
|
|
34
|
+
/**
|
|
35
|
+
* Host subscribes to events from the sub-module.
|
|
36
|
+
* Returns an unsubscribe function.
|
|
37
|
+
*/
|
|
38
|
+
_on(event: string, callback: EventCallback): () => void;
|
|
39
|
+
/**
|
|
40
|
+
* Cleans up all handlers and event listeners.
|
|
41
|
+
*/
|
|
42
|
+
destroy(): void;
|
|
43
|
+
private ensureBound;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACd,MAAM,YAAY,CAAC;AAKpB,qBAAa,UAAU;IACrB,SAAgB,QAAQ,EAAE,YAAY,CAAC;IAEvC,OAAO,CAAC,QAAQ,CAAwC;IACxD,OAAO,CAAC,cAAc,CAAyC;IAC/D,OAAO,CAAC,KAAK,CAAS;gBAEV,QAAQ,EAAE,YAAY;IAIlC;;;;OAIG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,IAAI;IAiBxD;;OAEG;IACG,IAAI,CAAC,CAAC,GAAG,OAAO,EACpB,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACnC,OAAO,CAAC,CAAC,CAAC;IAeb;;OAEG;IACI,MAAM,CAAC,CAAC,GAAG,OAAO,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACnC,cAAc,CAAC,CAAC,CAAC;IAuBpB;;OAEG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAIhC;;OAEG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI;IAaxC;;;OAGG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,MAAM,IAAI;IAWvD;;OAEG;IACH,OAAO,IAAI,IAAI;IAMf,OAAO,CAAC,WAAW;CAOpB"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wMCP — Web Module Connection Protocol
|
|
3
|
+
* WmcpClient — used inside the sub-module to call capabilities and emit events.
|
|
4
|
+
*/
|
|
5
|
+
import { WmcpError, WmcpBindError } from './errors.js';
|
|
6
|
+
import { validateParams } from './validator.js';
|
|
7
|
+
import { isAsyncIterable } from '../utils/stream.js';
|
|
8
|
+
export class WmcpClient {
|
|
9
|
+
manifest;
|
|
10
|
+
handlers = new Map();
|
|
11
|
+
eventListeners = new Map();
|
|
12
|
+
bound = false;
|
|
13
|
+
constructor(manifest) {
|
|
14
|
+
this.manifest = manifest;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Called by the host at mount time.
|
|
18
|
+
* Binds handler functions to each capability declared in the manifest.
|
|
19
|
+
* Throws WmcpBindError if a required capability is missing.
|
|
20
|
+
*/
|
|
21
|
+
_bind(handlers) {
|
|
22
|
+
for (const [name, cap] of Object.entries(this.manifest.capabilities)) {
|
|
23
|
+
if (!cap.optional && !handlers[name]) {
|
|
24
|
+
throw new WmcpBindError(name);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
for (const [name, handler] of Object.entries(handlers)) {
|
|
28
|
+
if (!this.manifest.capabilities[name]) {
|
|
29
|
+
console.warn(`[wMCP] Binding unknown capability: "${name}" — not declared in manifest`);
|
|
30
|
+
}
|
|
31
|
+
this.handlers.set(name, handler);
|
|
32
|
+
}
|
|
33
|
+
this.bound = true;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Invokes a request-mode capability.
|
|
37
|
+
*/
|
|
38
|
+
async call(capability, params = {}) {
|
|
39
|
+
this.ensureBound();
|
|
40
|
+
const handler = this.handlers.get(capability);
|
|
41
|
+
if (!handler) {
|
|
42
|
+
throw new WmcpError(`Capability not available: "${capability}"`);
|
|
43
|
+
}
|
|
44
|
+
const cap = this.manifest.capabilities[capability];
|
|
45
|
+
if (cap) {
|
|
46
|
+
validateParams(capability, cap, params);
|
|
47
|
+
}
|
|
48
|
+
return (await handler(params));
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Invokes a stream-mode capability, returning an async generator.
|
|
52
|
+
*/
|
|
53
|
+
async *stream(capability, params = {}) {
|
|
54
|
+
this.ensureBound();
|
|
55
|
+
const handler = this.handlers.get(capability);
|
|
56
|
+
if (!handler) {
|
|
57
|
+
throw new WmcpError(`Capability not available: "${capability}"`);
|
|
58
|
+
}
|
|
59
|
+
const cap = this.manifest.capabilities[capability];
|
|
60
|
+
if (cap) {
|
|
61
|
+
validateParams(capability, cap, params);
|
|
62
|
+
}
|
|
63
|
+
const result = handler(params);
|
|
64
|
+
if (isAsyncIterable(result)) {
|
|
65
|
+
for await (const chunk of result) {
|
|
66
|
+
yield chunk;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
yield (await result);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Checks if a capability has been bound (useful for optional capabilities).
|
|
75
|
+
*/
|
|
76
|
+
has(capability) {
|
|
77
|
+
return this.handlers.has(capability);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Sub-module calls this to emit an event to the host.
|
|
81
|
+
*/
|
|
82
|
+
emit(event, data) {
|
|
83
|
+
const listeners = this.eventListeners.get(event);
|
|
84
|
+
if (listeners) {
|
|
85
|
+
for (const cb of listeners) {
|
|
86
|
+
try {
|
|
87
|
+
cb(data);
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
console.error(`[wMCP] Error in event listener for "${event}":`, err);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Host subscribes to events from the sub-module.
|
|
97
|
+
* Returns an unsubscribe function.
|
|
98
|
+
*/
|
|
99
|
+
_on(event, callback) {
|
|
100
|
+
if (!this.eventListeners.has(event)) {
|
|
101
|
+
this.eventListeners.set(event, new Set());
|
|
102
|
+
}
|
|
103
|
+
this.eventListeners.get(event).add(callback);
|
|
104
|
+
return () => {
|
|
105
|
+
this.eventListeners.get(event)?.delete(callback);
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Cleans up all handlers and event listeners.
|
|
110
|
+
*/
|
|
111
|
+
destroy() {
|
|
112
|
+
this.handlers.clear();
|
|
113
|
+
this.eventListeners.clear();
|
|
114
|
+
this.bound = false;
|
|
115
|
+
}
|
|
116
|
+
ensureBound() {
|
|
117
|
+
if (!this.bound) {
|
|
118
|
+
throw new WmcpError('WmcpClient is not bound. The host must call _bind() before invoking capabilities.');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,OAAO,UAAU;IACL,QAAQ,CAAe;IAE/B,QAAQ,GAAG,IAAI,GAAG,EAA6B,CAAC;IAChD,cAAc,GAAG,IAAI,GAAG,EAA8B,CAAC;IACvD,KAAK,GAAG,KAAK,CAAC;IAEtB,YAAY,QAAsB;QAChC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,QAA2C;QAC/C,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YACrE,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrC,MAAM,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,OAAO,CAAC,IAAI,CAAC,uCAAuC,IAAI,8BAA8B,CAAC,CAAC;YAC1F,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI,CACR,UAAkB,EAClB,SAAkC,EAAE;QAEpC,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,SAAS,CAAC,8BAA8B,UAAU,GAAG,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QACnD,IAAI,GAAG,EAAE,CAAC;YACR,cAAc,CAAC,UAAU,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAM,CAAC;IACtC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,CAAC,MAAM,CACX,UAAkB,EAClB,SAAkC,EAAE;QAEpC,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,SAAS,CAAC,8BAA8B,UAAU,GAAG,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QACnD,IAAI,GAAG,EAAE,CAAC;YACR,cAAc,CAAC,UAAU,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAC1C,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAE/B,IAAI,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBACjC,MAAM,KAAU,CAAC;YACnB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,MAAM,MAAM,CAAM,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,UAAkB;QACpB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,KAAa,EAAE,IAAa;QAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjD,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;gBAC3B,IAAI,CAAC;oBACH,EAAE,CAAC,IAAI,CAAC,CAAC;gBACX,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,uCAAuC,KAAK,IAAI,EAAE,GAAG,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,GAAG,CAAC,KAAa,EAAE,QAAuB;QACxC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QAC5C,CAAC;QACD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAE9C,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACnD,CAAC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,OAAO;QACL,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,SAAS,CACjB,mFAAmF,CACpF,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wMCP — Web Module Connection Protocol
|
|
3
|
+
* Error classes
|
|
4
|
+
*/
|
|
5
|
+
export declare class WmcpError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/** Thrown when a required capability is not bound by the host */
|
|
9
|
+
export declare class WmcpBindError extends WmcpError {
|
|
10
|
+
readonly capability: string;
|
|
11
|
+
constructor(capability: string);
|
|
12
|
+
}
|
|
13
|
+
/** Thrown when an HTTP-backed capability call fails */
|
|
14
|
+
export declare class WmcpApiError extends WmcpError {
|
|
15
|
+
readonly status: number;
|
|
16
|
+
readonly body: string;
|
|
17
|
+
constructor(status: number, body: string);
|
|
18
|
+
}
|
|
19
|
+
/** Thrown when params or manifest fail validation */
|
|
20
|
+
export declare class WmcpValidationError extends WmcpError {
|
|
21
|
+
readonly field: string;
|
|
22
|
+
constructor(field: string, message: string);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAED,iEAAiE;AACjE,qBAAa,aAAc,SAAQ,SAAS;IAC1C,SAAgB,UAAU,EAAE,MAAM,CAAC;gBAEvB,UAAU,EAAE,MAAM;CAK/B;AAED,uDAAuD;AACvD,qBAAa,YAAa,SAAQ,SAAS;IACzC,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,IAAI,EAAE,MAAM,CAAC;gBAEjB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAMzC;AAED,qDAAqD;AACrD,qBAAa,mBAAoB,SAAQ,SAAS;IAChD,SAAgB,KAAK,EAAE,MAAM,CAAC;gBAElB,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK3C"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wMCP — Web Module Connection Protocol
|
|
3
|
+
* Error classes
|
|
4
|
+
*/
|
|
5
|
+
export class WmcpError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = 'WmcpError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** Thrown when a required capability is not bound by the host */
|
|
12
|
+
export class WmcpBindError extends WmcpError {
|
|
13
|
+
capability;
|
|
14
|
+
constructor(capability) {
|
|
15
|
+
super(`Missing handler for required capability: "${capability}"`);
|
|
16
|
+
this.name = 'WmcpBindError';
|
|
17
|
+
this.capability = capability;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Thrown when an HTTP-backed capability call fails */
|
|
21
|
+
export class WmcpApiError extends WmcpError {
|
|
22
|
+
status;
|
|
23
|
+
body;
|
|
24
|
+
constructor(status, body) {
|
|
25
|
+
super(`API error ${status}: ${body}`);
|
|
26
|
+
this.name = 'WmcpApiError';
|
|
27
|
+
this.status = status;
|
|
28
|
+
this.body = body;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Thrown when params or manifest fail validation */
|
|
32
|
+
export class WmcpValidationError extends WmcpError {
|
|
33
|
+
field;
|
|
34
|
+
constructor(field, message) {
|
|
35
|
+
super(`Validation error on "${field}": ${message}`);
|
|
36
|
+
this.name = 'WmcpValidationError';
|
|
37
|
+
this.field = field;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,iEAAiE;AACjE,MAAM,OAAO,aAAc,SAAQ,SAAS;IAC1B,UAAU,CAAS;IAEnC,YAAY,UAAkB;QAC5B,KAAK,CAAC,6CAA6C,UAAU,GAAG,CAAC,CAAC;QAClE,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED,uDAAuD;AACvD,MAAM,OAAO,YAAa,SAAQ,SAAS;IACzB,MAAM,CAAS;IACf,IAAI,CAAS;IAE7B,YAAY,MAAc,EAAE,IAAY;QACtC,KAAK,CAAC,aAAa,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,qDAAqD;AACrD,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IAChC,KAAK,CAAS;IAE9B,YAAY,KAAa,EAAE,OAAe;QACxC,KAAK,CAAC,wBAAwB,KAAK,MAAM,OAAO,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wMCP — Web Module Connection Protocol
|
|
3
|
+
* WmcpHost — used inside the host application to bind capabilities and subscribe to events.
|
|
4
|
+
*/
|
|
5
|
+
import type { WmcpHostConfig, CapabilityBinding, CapabilityHandler, EventCallback } from './types.js';
|
|
6
|
+
import { WmcpClient } from './client.js';
|
|
7
|
+
export declare class WmcpHost {
|
|
8
|
+
private client;
|
|
9
|
+
private config;
|
|
10
|
+
private fetchFn;
|
|
11
|
+
private unsubscribes;
|
|
12
|
+
constructor(client: WmcpClient, config: WmcpHostConfig);
|
|
13
|
+
/**
|
|
14
|
+
* Binds capability implementations to the client.
|
|
15
|
+
*
|
|
16
|
+
* Each entry can be either:
|
|
17
|
+
* - A CapabilityAdapter object (CSR): resolved to HTTP fetch through the proxy
|
|
18
|
+
* - A CapabilityHandler function (SSR): called directly (e.g. Next.js server action with 'use server')
|
|
19
|
+
*
|
|
20
|
+
* This allows mixing CSR and SSR bindings per capability in a single call:
|
|
21
|
+
*
|
|
22
|
+
* ```ts
|
|
23
|
+
* host.connect({
|
|
24
|
+
* 'counter:get': getCounterServerAction, // SSR — direct function
|
|
25
|
+
* 'counter:increment': { // CSR — HTTP adapter
|
|
26
|
+
* resolve: (p) => ({ method: 'POST', path: '/counter/increment', body: p }),
|
|
27
|
+
* },
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
connect(bindings: Record<string, CapabilityBinding>): void;
|
|
32
|
+
/**
|
|
33
|
+
* Convenience: bind all handlers as direct functions (bypass HTTP adapter layer).
|
|
34
|
+
* Useful for in-memory / mock integrations where every capability is a function.
|
|
35
|
+
*/
|
|
36
|
+
connectDirect(handlers: Record<string, CapabilityHandler>): void;
|
|
37
|
+
/**
|
|
38
|
+
* Subscribe to an event emitted by the sub-module.
|
|
39
|
+
* Returns an unsubscribe function.
|
|
40
|
+
*/
|
|
41
|
+
on(event: string, callback: EventCallback): () => void;
|
|
42
|
+
/**
|
|
43
|
+
* Cleans up all event subscriptions.
|
|
44
|
+
*/
|
|
45
|
+
destroy(): void;
|
|
46
|
+
private resolveHeaders;
|
|
47
|
+
private createHandler;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/core/host.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,cAAc,EAEd,iBAAiB,EACjB,iBAAiB,EAEjB,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,YAAY,CAAyB;gBAEjC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc;IAMtD;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,IAAI;IAc1D;;;OAGG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,IAAI;IAIhE;;;OAGG;IACH,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,MAAM,IAAI;IAMtD;;OAEG;IACH,OAAO,IAAI,IAAI;YAOD,cAAc;YAQd,aAAa;CA8C5B"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wMCP — Web Module Connection Protocol
|
|
3
|
+
* WmcpHost — used inside the host application to bind capabilities and subscribe to events.
|
|
4
|
+
*/
|
|
5
|
+
import { WmcpApiError } from './errors.js';
|
|
6
|
+
import { parseSSE } from '../utils/stream.js';
|
|
7
|
+
export class WmcpHost {
|
|
8
|
+
client;
|
|
9
|
+
config;
|
|
10
|
+
fetchFn;
|
|
11
|
+
unsubscribes = [];
|
|
12
|
+
constructor(client, config) {
|
|
13
|
+
this.client = client;
|
|
14
|
+
this.config = config;
|
|
15
|
+
this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Binds capability implementations to the client.
|
|
19
|
+
*
|
|
20
|
+
* Each entry can be either:
|
|
21
|
+
* - A CapabilityAdapter object (CSR): resolved to HTTP fetch through the proxy
|
|
22
|
+
* - A CapabilityHandler function (SSR): called directly (e.g. Next.js server action with 'use server')
|
|
23
|
+
*
|
|
24
|
+
* This allows mixing CSR and SSR bindings per capability in a single call:
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* host.connect({
|
|
28
|
+
* 'counter:get': getCounterServerAction, // SSR — direct function
|
|
29
|
+
* 'counter:increment': { // CSR — HTTP adapter
|
|
30
|
+
* resolve: (p) => ({ method: 'POST', path: '/counter/increment', body: p }),
|
|
31
|
+
* },
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
connect(bindings) {
|
|
36
|
+
const handlers = {};
|
|
37
|
+
for (const [capability, binding] of Object.entries(bindings)) {
|
|
38
|
+
if (typeof binding === 'function') {
|
|
39
|
+
handlers[capability] = binding;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
handlers[capability] = (params) => this.createHandler(binding, params);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
this.client._bind(handlers);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Convenience: bind all handlers as direct functions (bypass HTTP adapter layer).
|
|
49
|
+
* Useful for in-memory / mock integrations where every capability is a function.
|
|
50
|
+
*/
|
|
51
|
+
connectDirect(handlers) {
|
|
52
|
+
this.client._bind(handlers);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Subscribe to an event emitted by the sub-module.
|
|
56
|
+
* Returns an unsubscribe function.
|
|
57
|
+
*/
|
|
58
|
+
on(event, callback) {
|
|
59
|
+
const unsub = this.client._on(event, callback);
|
|
60
|
+
this.unsubscribes.push(unsub);
|
|
61
|
+
return unsub;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Cleans up all event subscriptions.
|
|
65
|
+
*/
|
|
66
|
+
destroy() {
|
|
67
|
+
for (const unsub of this.unsubscribes) {
|
|
68
|
+
unsub();
|
|
69
|
+
}
|
|
70
|
+
this.unsubscribes = [];
|
|
71
|
+
}
|
|
72
|
+
async resolveHeaders(provider) {
|
|
73
|
+
if (!provider)
|
|
74
|
+
return {};
|
|
75
|
+
if (typeof provider === 'function') {
|
|
76
|
+
return await provider();
|
|
77
|
+
}
|
|
78
|
+
return provider;
|
|
79
|
+
}
|
|
80
|
+
async createHandler(adapter, params) {
|
|
81
|
+
const { method, path, body, query } = adapter.resolve(params);
|
|
82
|
+
let url = `${this.config.baseUrl}${path}`;
|
|
83
|
+
if (query) {
|
|
84
|
+
const qs = new URLSearchParams(query).toString();
|
|
85
|
+
if (qs)
|
|
86
|
+
url += `?${qs}`;
|
|
87
|
+
}
|
|
88
|
+
const resolved = await this.resolveHeaders(this.config.headers);
|
|
89
|
+
const headers = { ...resolved };
|
|
90
|
+
const init = { method, headers };
|
|
91
|
+
if (body !== undefined) {
|
|
92
|
+
if (body instanceof Blob || body instanceof ArrayBuffer) {
|
|
93
|
+
init.body = body;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
headers['Content-Type'] = 'application/json';
|
|
97
|
+
init.body = JSON.stringify(body);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const response = await this.fetchFn(url, init);
|
|
101
|
+
if (adapter.stream) {
|
|
102
|
+
return parseSSE(response);
|
|
103
|
+
}
|
|
104
|
+
if (!response.ok) {
|
|
105
|
+
const errorBody = await response.text();
|
|
106
|
+
throw new WmcpApiError(response.status, errorBody);
|
|
107
|
+
}
|
|
108
|
+
const contentType = response.headers.get('Content-Type') ?? '';
|
|
109
|
+
if (contentType.includes('application/json')) {
|
|
110
|
+
return response.json();
|
|
111
|
+
}
|
|
112
|
+
if (contentType.includes('application/octet-stream') || contentType.includes('blob')) {
|
|
113
|
+
return response.blob();
|
|
114
|
+
}
|
|
115
|
+
return response.text();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/core/host.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wMCP — Web Module Connection Protocol
|
|
3
|
+
* Package entry point
|
|
4
|
+
*/
|
|
5
|
+
export { WmcpClient } from './client.js';
|
|
6
|
+
export { WmcpHost } from './host.js';
|
|
7
|
+
export { validateManifest, validateParams } from './validator.js';
|
|
8
|
+
export { WmcpError, WmcpBindError, WmcpApiError, WmcpValidationError, } from './errors.js';
|
|
9
|
+
export { parseSSE, isAsyncIterable } from '../utils/stream.js';
|
|
10
|
+
export type { WmcpManifest, WmcpModuleInfo, WmcpMountConfig, WmcpCapability, WmcpParamDef, WmcpTypeDef, WmcpHint, WmcpEvent, WmcpConfigParam, CapabilityHandler, CapabilityAdapter, CapabilityBinding, HeadersProvider, WmcpHostConfig, WmcpMountOptions, EventCallback, } from './types.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EACL,SAAS,EACT,aAAa,EACb,YAAY,EACZ,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE/D,YAAY,EACV,YAAY,EACZ,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,SAAS,EACT,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,aAAa,GACd,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wMCP — Web Module Connection Protocol
|
|
3
|
+
* Package entry point
|
|
4
|
+
*/
|
|
5
|
+
export { WmcpClient } from './client.js';
|
|
6
|
+
export { WmcpHost } from './host.js';
|
|
7
|
+
export { validateManifest, validateParams } from './validator.js';
|
|
8
|
+
export { WmcpError, WmcpBindError, WmcpApiError, WmcpValidationError, } from './errors.js';
|
|
9
|
+
export { parseSSE, isAsyncIterable } from '../utils/stream.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EACL,SAAS,EACT,aAAa,EACb,YAAY,EACZ,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wMCP — Web Module Connection Protocol
|
|
3
|
+
* Core type definitions
|
|
4
|
+
*/
|
|
5
|
+
export interface WmcpManifest {
|
|
6
|
+
/** Protocol version (e.g. "1.0") */
|
|
7
|
+
wmcp: string;
|
|
8
|
+
/** Module identity */
|
|
9
|
+
module: WmcpModuleInfo;
|
|
10
|
+
/** How the module mounts into the DOM */
|
|
11
|
+
mount: WmcpMountConfig;
|
|
12
|
+
/** Capabilities the module requires from the host */
|
|
13
|
+
capabilities: Record<string, WmcpCapability>;
|
|
14
|
+
/** Events the module emits to the host */
|
|
15
|
+
events?: Record<string, WmcpEvent>;
|
|
16
|
+
/** Configuration the module accepts at mount time */
|
|
17
|
+
config?: Record<string, WmcpConfigParam>;
|
|
18
|
+
}
|
|
19
|
+
export interface WmcpModuleInfo {
|
|
20
|
+
/** Package name (e.g. "@aurorah/wmcp-rich-editor") */
|
|
21
|
+
name: string;
|
|
22
|
+
/** Semver version */
|
|
23
|
+
version: string;
|
|
24
|
+
/** Human-readable description */
|
|
25
|
+
description?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface WmcpMountConfig {
|
|
28
|
+
/** Entry point file relative to package root */
|
|
29
|
+
entry: string;
|
|
30
|
+
/** CSS file to load */
|
|
31
|
+
styles?: string;
|
|
32
|
+
/** Default container element ID */
|
|
33
|
+
defaultElementId?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface WmcpCapability {
|
|
36
|
+
/** Human-readable description (useful for AI and docs) */
|
|
37
|
+
description: string;
|
|
38
|
+
/** Whether this capability is optional. Default: false (required) */
|
|
39
|
+
optional?: boolean;
|
|
40
|
+
/** Request/response mode */
|
|
41
|
+
mode: 'request' | 'stream';
|
|
42
|
+
/** Parameter definitions */
|
|
43
|
+
params?: Record<string, WmcpParamDef>;
|
|
44
|
+
/** Return type definition */
|
|
45
|
+
returns?: WmcpTypeDef;
|
|
46
|
+
/** Hint for host adapter generation: suggested HTTP method + path template */
|
|
47
|
+
hint?: WmcpHint;
|
|
48
|
+
}
|
|
49
|
+
export interface WmcpParamDef {
|
|
50
|
+
type: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'blob';
|
|
51
|
+
required?: boolean;
|
|
52
|
+
description?: string;
|
|
53
|
+
enum?: unknown[];
|
|
54
|
+
}
|
|
55
|
+
export interface WmcpTypeDef {
|
|
56
|
+
type: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'void' | 'blob';
|
|
57
|
+
description?: string;
|
|
58
|
+
}
|
|
59
|
+
export interface WmcpHint {
|
|
60
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
61
|
+
path: string;
|
|
62
|
+
}
|
|
63
|
+
export interface WmcpEvent {
|
|
64
|
+
/** Human-readable description */
|
|
65
|
+
description: string;
|
|
66
|
+
/** Data shape emitted with the event */
|
|
67
|
+
data: Record<string, WmcpTypeDef>;
|
|
68
|
+
}
|
|
69
|
+
export interface WmcpConfigParam {
|
|
70
|
+
type: 'string' | 'number' | 'boolean' | 'array' | 'object';
|
|
71
|
+
required?: boolean;
|
|
72
|
+
default?: unknown;
|
|
73
|
+
enum?: unknown[];
|
|
74
|
+
description?: string;
|
|
75
|
+
}
|
|
76
|
+
/** Handler function the host provides for a capability */
|
|
77
|
+
export type CapabilityHandler = (params: Record<string, unknown>) => Promise<unknown> | AsyncIterable<unknown>;
|
|
78
|
+
/** Callback for event subscriptions */
|
|
79
|
+
export type EventCallback = (data: unknown) => void;
|
|
80
|
+
/** Adapter definition used by WmcpHost to map capabilities to HTTP endpoints (CSR) */
|
|
81
|
+
export interface CapabilityAdapter {
|
|
82
|
+
/** Resolves params into an HTTP request shape */
|
|
83
|
+
resolve: (params: Record<string, unknown>) => {
|
|
84
|
+
method: string;
|
|
85
|
+
path: string;
|
|
86
|
+
body?: unknown;
|
|
87
|
+
query?: Record<string, string>;
|
|
88
|
+
};
|
|
89
|
+
/** If true, the response is treated as an SSE stream */
|
|
90
|
+
stream?: boolean;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* A capability binding can be either:
|
|
94
|
+
* - A CapabilityAdapter object (CSR: resolved to HTTP fetch through proxy)
|
|
95
|
+
* - A CapabilityHandler function (SSR: direct server action or in-memory handler)
|
|
96
|
+
*
|
|
97
|
+
* This allows mixing CSR and SSR bindings per capability in a single connect() call.
|
|
98
|
+
*/
|
|
99
|
+
export type CapabilityBinding = CapabilityAdapter | CapabilityHandler;
|
|
100
|
+
/** Static headers or a sync/async function that returns headers per request */
|
|
101
|
+
export type HeadersProvider = Record<string, string> | (() => Record<string, string>) | (() => Promise<Record<string, string>>);
|
|
102
|
+
/** Configuration for WmcpHost */
|
|
103
|
+
export interface WmcpHostConfig {
|
|
104
|
+
/** Base URL for API requests (e.g. "/api/v1" or "http://localhost:8000/api/v1") */
|
|
105
|
+
baseUrl: string;
|
|
106
|
+
/**
|
|
107
|
+
* Headers to inject into HTTP-backed capability requests.
|
|
108
|
+
* Can be a static object or a sync/async function for per-request headers
|
|
109
|
+
* (e.g. reading API keys from env, session cookies, or token refresh).
|
|
110
|
+
*/
|
|
111
|
+
headers?: HeadersProvider;
|
|
112
|
+
/** Custom fetch implementation (defaults to globalThis.fetch) */
|
|
113
|
+
fetch?: typeof globalThis.fetch;
|
|
114
|
+
}
|
|
115
|
+
/** Mount options passed to the sub-module's mount function */
|
|
116
|
+
export interface WmcpMountOptions {
|
|
117
|
+
/** Runtime configuration values */
|
|
118
|
+
config?: Record<string, unknown>;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wMCP — Web Module Connection Protocol
|
|
3
|
+
* Manifest and parameter validation
|
|
4
|
+
*/
|
|
5
|
+
import type { WmcpManifest, WmcpCapability } from './types.js';
|
|
6
|
+
export declare function validateManifest(manifest: unknown): asserts manifest is WmcpManifest;
|
|
7
|
+
/**
|
|
8
|
+
* Validates params against a capability's param definitions.
|
|
9
|
+
* Checks that all required params are present and have correct types.
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateParams(capabilityName: string, capability: WmcpCapability, params: Record<string, unknown>): void;
|
|
12
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAK/D,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,IAAI,YAAY,CAwCpF;AAqBD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,cAAc,EAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,IAAI,CAiCN"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wMCP — Web Module Connection Protocol
|
|
3
|
+
* Manifest and parameter validation
|
|
4
|
+
*/
|
|
5
|
+
import { WmcpValidationError } from './errors.js';
|
|
6
|
+
const SUPPORTED_VERSIONS = ['1.0'];
|
|
7
|
+
export function validateManifest(manifest) {
|
|
8
|
+
if (!manifest || typeof manifest !== 'object') {
|
|
9
|
+
throw new WmcpValidationError('manifest', 'Must be a non-null object');
|
|
10
|
+
}
|
|
11
|
+
const m = manifest;
|
|
12
|
+
if (typeof m.wmcp !== 'string' || !SUPPORTED_VERSIONS.includes(m.wmcp)) {
|
|
13
|
+
throw new WmcpValidationError('wmcp', `Must be one of: ${SUPPORTED_VERSIONS.join(', ')}. Got: "${m.wmcp}"`);
|
|
14
|
+
}
|
|
15
|
+
if (!m.module || typeof m.module !== 'object') {
|
|
16
|
+
throw new WmcpValidationError('module', 'Must be an object');
|
|
17
|
+
}
|
|
18
|
+
const mod = m.module;
|
|
19
|
+
if (typeof mod.name !== 'string' || !mod.name) {
|
|
20
|
+
throw new WmcpValidationError('module.name', 'Must be a non-empty string');
|
|
21
|
+
}
|
|
22
|
+
if (typeof mod.version !== 'string' || !mod.version) {
|
|
23
|
+
throw new WmcpValidationError('module.version', 'Must be a non-empty string');
|
|
24
|
+
}
|
|
25
|
+
if (!m.mount || typeof m.mount !== 'object') {
|
|
26
|
+
throw new WmcpValidationError('mount', 'Must be an object');
|
|
27
|
+
}
|
|
28
|
+
const mount = m.mount;
|
|
29
|
+
if (typeof mount.entry !== 'string' || !mount.entry) {
|
|
30
|
+
throw new WmcpValidationError('mount.entry', 'Must be a non-empty string');
|
|
31
|
+
}
|
|
32
|
+
if (!m.capabilities || typeof m.capabilities !== 'object') {
|
|
33
|
+
throw new WmcpValidationError('capabilities', 'Must be an object');
|
|
34
|
+
}
|
|
35
|
+
for (const [name, cap] of Object.entries(m.capabilities)) {
|
|
36
|
+
validateCapability(name, cap);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function validateCapability(name, cap) {
|
|
40
|
+
if (!cap || typeof cap !== 'object') {
|
|
41
|
+
throw new WmcpValidationError(`capabilities.${name}`, 'Must be an object');
|
|
42
|
+
}
|
|
43
|
+
const c = cap;
|
|
44
|
+
if (typeof c.description !== 'string') {
|
|
45
|
+
throw new WmcpValidationError(`capabilities.${name}.description`, 'Must be a string');
|
|
46
|
+
}
|
|
47
|
+
if (c.mode !== 'request' && c.mode !== 'stream') {
|
|
48
|
+
throw new WmcpValidationError(`capabilities.${name}.mode`, 'Must be "request" or "stream"');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Validates params against a capability's param definitions.
|
|
53
|
+
* Checks that all required params are present and have correct types.
|
|
54
|
+
*/
|
|
55
|
+
export function validateParams(capabilityName, capability, params) {
|
|
56
|
+
if (!capability.params)
|
|
57
|
+
return;
|
|
58
|
+
for (const [paramName, def] of Object.entries(capability.params)) {
|
|
59
|
+
const value = params[paramName];
|
|
60
|
+
if (def.required && (value === undefined || value === null)) {
|
|
61
|
+
throw new WmcpValidationError(`${capabilityName}.params.${paramName}`, 'Required parameter is missing');
|
|
62
|
+
}
|
|
63
|
+
if (value !== undefined && value !== null) {
|
|
64
|
+
const actualType = Array.isArray(value) ? 'array' : typeof value;
|
|
65
|
+
const allowedTypes = [def.type];
|
|
66
|
+
if (def.type === 'blob')
|
|
67
|
+
allowedTypes.push('object');
|
|
68
|
+
if (!allowedTypes.includes(actualType)) {
|
|
69
|
+
throw new WmcpValidationError(`${capabilityName}.params.${paramName}`, `Expected type "${def.type}", got "${actualType}"`);
|
|
70
|
+
}
|
|
71
|
+
if (def.enum && !def.enum.includes(value)) {
|
|
72
|
+
throw new WmcpValidationError(`${capabilityName}.params.${paramName}`, `Value must be one of: ${def.enum.join(', ')}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wMCP — Web Module Connection Protocol
|
|
3
|
+
* SSE / stream parsing helpers
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Parses an SSE (Server-Sent Events) response body into an async generator.
|
|
7
|
+
* Each `data:` line is JSON-parsed and yielded.
|
|
8
|
+
* Lines starting with `:` (comments) and empty lines are skipped.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseSSE(response: Response): AsyncGenerator<unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* Checks whether a value is an AsyncIterable.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isAsyncIterable(value: unknown): value is AsyncIterable<unknown>;
|
|
15
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/utils/stream.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,wBAAuB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,CAiD3E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAAC,OAAO,CAAC,CAM/E"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wMCP — Web Module Connection Protocol
|
|
3
|
+
* SSE / stream parsing helpers
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Parses an SSE (Server-Sent Events) response body into an async generator.
|
|
7
|
+
* Each `data:` line is JSON-parsed and yielded.
|
|
8
|
+
* Lines starting with `:` (comments) and empty lines are skipped.
|
|
9
|
+
*/
|
|
10
|
+
export async function* parseSSE(response) {
|
|
11
|
+
const body = response.body;
|
|
12
|
+
if (!body) {
|
|
13
|
+
throw new Error('Response body is null — cannot parse SSE stream');
|
|
14
|
+
}
|
|
15
|
+
const reader = body.getReader();
|
|
16
|
+
const decoder = new TextDecoder();
|
|
17
|
+
let buffer = '';
|
|
18
|
+
try {
|
|
19
|
+
while (true) {
|
|
20
|
+
const { done, value } = await reader.read();
|
|
21
|
+
if (done)
|
|
22
|
+
break;
|
|
23
|
+
buffer += decoder.decode(value, { stream: true });
|
|
24
|
+
const lines = buffer.split('\n');
|
|
25
|
+
buffer = lines.pop() ?? '';
|
|
26
|
+
for (const line of lines) {
|
|
27
|
+
const trimmed = line.trim();
|
|
28
|
+
if (!trimmed || trimmed.startsWith(':'))
|
|
29
|
+
continue;
|
|
30
|
+
if (trimmed.startsWith('data: ')) {
|
|
31
|
+
const payload = trimmed.slice(6);
|
|
32
|
+
if (payload === '[DONE]')
|
|
33
|
+
return;
|
|
34
|
+
try {
|
|
35
|
+
yield JSON.parse(payload);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
yield payload;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (buffer.trim().startsWith('data: ')) {
|
|
44
|
+
const payload = buffer.trim().slice(6);
|
|
45
|
+
if (payload !== '[DONE]') {
|
|
46
|
+
try {
|
|
47
|
+
yield JSON.parse(payload);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
yield payload;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
reader.releaseLock();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Checks whether a value is an AsyncIterable.
|
|
61
|
+
*/
|
|
62
|
+
export function isAsyncIterable(value) {
|
|
63
|
+
return (value !== null &&
|
|
64
|
+
typeof value === 'object' &&
|
|
65
|
+
Symbol.asyncIterator in value);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/utils/stream.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAkB;IAChD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,MAAM;YAEhB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC5B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,SAAS;gBAElD,IAAI,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACjC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBACjC,IAAI,OAAO,KAAK,QAAQ;wBAAE,OAAO;oBAEjC,IAAI,CAAC;wBACH,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;oBAC5B,CAAC;oBAAC,MAAM,CAAC;wBACP,MAAM,OAAO,CAAC;oBAChB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACvC,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAC5B,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,OAAO,CAAC;gBAChB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,CACL,KAAK,KAAK,IAAI;QACd,OAAO,KAAK,KAAK,QAAQ;QACzB,MAAM,CAAC,aAAa,IAAK,KAAgB,CAC1C,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aurorah/wmcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Web Module Connection Protocol (wMCP) — a standardized protocol for connecting encapsulated web UI modules to host applications",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"prepublishOnly": "npm run build",
|
|
20
|
+
"example:counter": "npx tsx examples/counter/host-app.ts",
|
|
21
|
+
"example:counter:server": "npx tsx examples/counter/mock-server.ts"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"wmcp",
|
|
25
|
+
"web-module-connection-protocol",
|
|
26
|
+
"module-protocol",
|
|
27
|
+
"micro-frontend",
|
|
28
|
+
"web-components",
|
|
29
|
+
"plugin-architecture"
|
|
30
|
+
],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"tsx": "^4.19.0",
|
|
34
|
+
"typescript": "^5.6.0"
|
|
35
|
+
}
|
|
36
|
+
}
|