@stackable-labs/sdk-extension-host 1.1.0 → 1.3.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 +103 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -45,6 +45,109 @@ function App() {
|
|
|
45
45
|
- **`CapabilityRPCHandler`** — handles capability requests from extension sandboxes
|
|
46
46
|
- **`SandboxManager`** — creates and destroys hidden iframe sandboxes per extension
|
|
47
47
|
|
|
48
|
+
## Building a local preview host
|
|
49
|
+
|
|
50
|
+
During extension development, you can create a lightweight preview host app in your extension repo to test your extension against the real SDK sandbox — no private monorepo required.
|
|
51
|
+
|
|
52
|
+
### Structure
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
packages/
|
|
56
|
+
├── extension/ ← your extension
|
|
57
|
+
└── preview/ ← local preview host
|
|
58
|
+
└── src/
|
|
59
|
+
├── main.tsx
|
|
60
|
+
├── App.tsx
|
|
61
|
+
└── mockData.json
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Preview App.tsx pattern
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import { ExtensionProvider, ExtensionSlot } from '@stackable-labs/sdk-extension-host';
|
|
68
|
+
import type { CapabilityHandlers } from '@stackable-labs/sdk-extension-host';
|
|
69
|
+
import { hostComponents } from '@stackable-labs/embeddables/components';
|
|
70
|
+
import type {
|
|
71
|
+
ApiRequest,
|
|
72
|
+
ExtensionRegistryEntry,
|
|
73
|
+
Permission,
|
|
74
|
+
ToastPayload,
|
|
75
|
+
} from '@stackable-labs/sdk-extension-contracts';
|
|
76
|
+
import manifestRaw from '../../extension/public/manifest.json';
|
|
77
|
+
import mockData from './mockData.json';
|
|
78
|
+
|
|
79
|
+
const manifest = {
|
|
80
|
+
...manifestRaw,
|
|
81
|
+
permissions: manifestRaw.permissions as Permission[],
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const extensions: ExtensionRegistryEntry[] = [
|
|
85
|
+
{
|
|
86
|
+
id: manifest.name.toLowerCase().replace(/\s+/g, '-'),
|
|
87
|
+
manifest,
|
|
88
|
+
bundleUrl: `http://localhost:${import.meta.env.VITE_EXTENSION_PORT || '5173'}`,
|
|
89
|
+
enabled: true,
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
const mockContext = { customerId: 'cust_123', customerEmail: 'dev@example.com' };
|
|
94
|
+
|
|
95
|
+
const capabilityHandlers: CapabilityHandlers = {
|
|
96
|
+
'data.query': async (payload: ApiRequest) => {
|
|
97
|
+
// return mock data based on payload.action
|
|
98
|
+
return mockData;
|
|
99
|
+
},
|
|
100
|
+
'actions.toast': async (payload: ToastPayload) => {
|
|
101
|
+
console.log('[Preview] toast:', payload);
|
|
102
|
+
},
|
|
103
|
+
'context.read': async () => mockContext,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export default function App() {
|
|
107
|
+
return (
|
|
108
|
+
<ExtensionProvider
|
|
109
|
+
extensions={extensions}
|
|
110
|
+
components={hostComponents()}
|
|
111
|
+
capabilityHandlers={capabilityHandlers}
|
|
112
|
+
>
|
|
113
|
+
{manifest.targets.map((target) => (
|
|
114
|
+
<ExtensionSlot key={target} target={target} context={mockContext} />
|
|
115
|
+
))}
|
|
116
|
+
</ExtensionProvider>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Wiring two dev servers with Turborepo
|
|
122
|
+
|
|
123
|
+
At the workspace root, add:
|
|
124
|
+
|
|
125
|
+
**.env**
|
|
126
|
+
```
|
|
127
|
+
VITE_EXTENSION_PORT=5173
|
|
128
|
+
VITE_PREVIEW_PORT=5174
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**turbo.json**
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"$schema": "https://turbo.build/schema.json",
|
|
135
|
+
"globalEnv": ["VITE_EXTENSION_PORT", "VITE_PREVIEW_PORT"],
|
|
136
|
+
"tasks": {
|
|
137
|
+
"dev": { "cache": false, "persistent": true }
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Run both servers with one command:
|
|
143
|
+
```bash
|
|
144
|
+
pnpm dev
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Extension runs at `:5173`, preview host at `:5174`. The preview host loads the extension bundle from the dev server, so edits to the extension hot-reload in the preview automatically.
|
|
148
|
+
|
|
149
|
+
See [sample-extension-commerce](https://github.com/agnostack/sample-extension-commerce) and [sample-extension-approvals](https://github.com/agnostack/sample-extension-approvals) for complete working examples.
|
|
150
|
+
|
|
48
151
|
## Changelog
|
|
49
152
|
|
|
50
153
|
See [npm version history](https://www.npmjs.com/package/@stackable-labs/sdk-extension-host?activeTab=versions).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackable-labs/sdk-extension-host",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@stackable-labs/sdk-extension-contracts": "1.
|
|
15
|
+
"@stackable-labs/sdk-extension-contracts": "1.3.0",
|
|
16
16
|
"@remote-dom/core": "1.x",
|
|
17
17
|
"@remote-dom/react": "1.x"
|
|
18
18
|
},
|