@stackable-labs/mcp-app-extension 0.8.0 → 0.10.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/dist/index.js +41 -8
- package/dist/server.js +41 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -43,12 +43,13 @@ export const appStore = createStore<AppState>({
|
|
|
43
43
|
{
|
|
44
44
|
path: "surfaces/Content.tsx",
|
|
45
45
|
title: "Content Surface with Loading State",
|
|
46
|
-
code: `import { ui, useStore, useContextData, Surface } from '@stackable-labs/sdk-extension-react'
|
|
46
|
+
code: `import { ui, useStore, useContextData, useSettings, Surface } from '@stackable-labs/sdk-extension-react'
|
|
47
47
|
import { appStore } from '../store'
|
|
48
48
|
|
|
49
49
|
export function Content() {
|
|
50
50
|
const viewState = useStore(appStore, (s) => s.viewState)
|
|
51
51
|
const { loading } = useContextData()
|
|
52
|
+
const settings = useSettings() // Non-secret settings from settingsSchema
|
|
52
53
|
|
|
53
54
|
if (loading) {
|
|
54
55
|
return (
|
|
@@ -143,19 +144,33 @@ export function createApi(query: QueryFn) {
|
|
|
143
144
|
}
|
|
144
145
|
|
|
145
146
|
// \u2500\u2500 data.fetch wrapper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
147
|
+
//
|
|
148
|
+
// For API keys and secrets, use {{settings.xxx}} placeholders in headers.
|
|
149
|
+
// The proxy resolves them server-side \u2014 the real secret never enters extension code.
|
|
150
|
+
// Declare secret fields in manifest.json settingsSchema with "secret": true.
|
|
146
151
|
|
|
147
152
|
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL as string
|
|
148
153
|
|
|
149
154
|
export function createFetchApi(fetch: FetchFn) {
|
|
150
155
|
return {
|
|
151
156
|
async getItems(): Promise<unknown[]> {
|
|
152
|
-
const result = await fetch(\`\${API_BASE_URL}/items\`, {
|
|
157
|
+
const result = await fetch(\`\${API_BASE_URL}/items\`, {
|
|
158
|
+
method: 'GET',
|
|
159
|
+
headers: {
|
|
160
|
+
'X-API-Key': '{{settings.apiKey}}',
|
|
161
|
+
},
|
|
162
|
+
})
|
|
153
163
|
if (!result.ok) throw new Error(\`getItems failed: \${result.status}\`)
|
|
154
164
|
return result.data as unknown[]
|
|
155
165
|
},
|
|
156
166
|
|
|
157
167
|
async getItem(itemId: string): Promise<unknown> {
|
|
158
|
-
const result = await fetch(\`\${API_BASE_URL}/items/\${itemId}\`, {
|
|
168
|
+
const result = await fetch(\`\${API_BASE_URL}/items/\${itemId}\`, {
|
|
169
|
+
method: 'GET',
|
|
170
|
+
headers: {
|
|
171
|
+
'X-API-Key': '{{settings.apiKey}}',
|
|
172
|
+
},
|
|
173
|
+
})
|
|
159
174
|
if (!result.ok) throw new Error(\`getItem failed: \${result.status}\`)
|
|
160
175
|
return result.data as unknown
|
|
161
176
|
},
|
|
@@ -182,12 +197,13 @@ export const appStore = createStore<AppState>({
|
|
|
182
197
|
{
|
|
183
198
|
path: "surfaces/Content.tsx",
|
|
184
199
|
title: "Current Content Surface",
|
|
185
|
-
code: `import { ui, useStore, useContextData, Surface } from '@stackable-labs/sdk-extension-react'
|
|
200
|
+
code: `import { ui, useStore, useContextData, useSettings, Surface } from '@stackable-labs/sdk-extension-react'
|
|
186
201
|
import { appStore } from '../store'
|
|
187
202
|
|
|
188
203
|
export function Content() {
|
|
189
204
|
const viewState = useStore(appStore, (s) => s.viewState)
|
|
190
205
|
const { loading } = useContextData()
|
|
206
|
+
const settings = useSettings() // Non-secret settings from settingsSchema
|
|
191
207
|
|
|
192
208
|
if (loading) {
|
|
193
209
|
return (
|
|
@@ -251,19 +267,33 @@ export function createApi(query: QueryFn) {
|
|
|
251
267
|
}
|
|
252
268
|
|
|
253
269
|
// \u2500\u2500 data.fetch wrapper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
270
|
+
//
|
|
271
|
+
// For API keys and secrets, use {{settings.xxx}} placeholders in headers.
|
|
272
|
+
// The proxy resolves them server-side \u2014 the real secret never enters extension code.
|
|
273
|
+
// Declare secret fields in manifest.json settingsSchema with "secret": true.
|
|
254
274
|
|
|
255
275
|
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL as string
|
|
256
276
|
|
|
257
277
|
export function createFetchApi(fetch: FetchFn) {
|
|
258
278
|
return {
|
|
259
279
|
async getItems(): Promise<unknown[]> {
|
|
260
|
-
const result = await fetch(\`\${API_BASE_URL}/items\`, {
|
|
280
|
+
const result = await fetch(\`\${API_BASE_URL}/items\`, {
|
|
281
|
+
method: 'GET',
|
|
282
|
+
headers: {
|
|
283
|
+
'X-API-Key': '{{settings.apiKey}}',
|
|
284
|
+
},
|
|
285
|
+
})
|
|
261
286
|
if (!result.ok) throw new Error(\`getItems failed: \${result.status}\`)
|
|
262
287
|
return result.data as unknown[]
|
|
263
288
|
},
|
|
264
289
|
|
|
265
290
|
async getItem(itemId: string): Promise<unknown> {
|
|
266
|
-
const result = await fetch(\`\${API_BASE_URL}/items/\${itemId}\`, {
|
|
291
|
+
const result = await fetch(\`\${API_BASE_URL}/items/\${itemId}\`, {
|
|
292
|
+
method: 'GET',
|
|
293
|
+
headers: {
|
|
294
|
+
'X-API-Key': '{{settings.apiKey}}',
|
|
295
|
+
},
|
|
296
|
+
})
|
|
267
297
|
if (!result.ok) throw new Error(\`getItem failed: \${result.status}\`)
|
|
268
298
|
return result.data as unknown
|
|
269
299
|
},
|
|
@@ -3682,8 +3712,11 @@ var CAPABILITY_SNIPPETS2 = {
|
|
|
3682
3712
|
const result = await capabilities.data.query({ path: '/your-endpoint', method: 'GET' })`,
|
|
3683
3713
|
"data.fetch": `const capabilities = useCapabilities()
|
|
3684
3714
|
const response = await capabilities.data.fetch('https://api.example.com/endpoint')`,
|
|
3685
|
-
"context.read":
|
|
3686
|
-
const
|
|
3715
|
+
"context.read": `// Read host context + extension settings
|
|
3716
|
+
const { customerId, settings } = useContextData()
|
|
3717
|
+
|
|
3718
|
+
// Or use the convenience hook for settings only
|
|
3719
|
+
const settings = useSettings()`,
|
|
3687
3720
|
"actions.toast": `const capabilities = useCapabilities()
|
|
3688
3721
|
capabilities.actions.toast({ type: 'success', message: 'Done!' })`,
|
|
3689
3722
|
"actions.invoke": `const capabilities = useCapabilities()
|
package/dist/server.js
CHANGED
|
@@ -41,12 +41,13 @@ export const appStore = createStore<AppState>({
|
|
|
41
41
|
{
|
|
42
42
|
path: "surfaces/Content.tsx",
|
|
43
43
|
title: "Content Surface with Loading State",
|
|
44
|
-
code: `import { ui, useStore, useContextData, Surface } from '@stackable-labs/sdk-extension-react'
|
|
44
|
+
code: `import { ui, useStore, useContextData, useSettings, Surface } from '@stackable-labs/sdk-extension-react'
|
|
45
45
|
import { appStore } from '../store'
|
|
46
46
|
|
|
47
47
|
export function Content() {
|
|
48
48
|
const viewState = useStore(appStore, (s) => s.viewState)
|
|
49
49
|
const { loading } = useContextData()
|
|
50
|
+
const settings = useSettings() // Non-secret settings from settingsSchema
|
|
50
51
|
|
|
51
52
|
if (loading) {
|
|
52
53
|
return (
|
|
@@ -141,19 +142,33 @@ export function createApi(query: QueryFn) {
|
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
// \u2500\u2500 data.fetch wrapper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
145
|
+
//
|
|
146
|
+
// For API keys and secrets, use {{settings.xxx}} placeholders in headers.
|
|
147
|
+
// The proxy resolves them server-side \u2014 the real secret never enters extension code.
|
|
148
|
+
// Declare secret fields in manifest.json settingsSchema with "secret": true.
|
|
144
149
|
|
|
145
150
|
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL as string
|
|
146
151
|
|
|
147
152
|
export function createFetchApi(fetch: FetchFn) {
|
|
148
153
|
return {
|
|
149
154
|
async getItems(): Promise<unknown[]> {
|
|
150
|
-
const result = await fetch(\`\${API_BASE_URL}/items\`, {
|
|
155
|
+
const result = await fetch(\`\${API_BASE_URL}/items\`, {
|
|
156
|
+
method: 'GET',
|
|
157
|
+
headers: {
|
|
158
|
+
'X-API-Key': '{{settings.apiKey}}',
|
|
159
|
+
},
|
|
160
|
+
})
|
|
151
161
|
if (!result.ok) throw new Error(\`getItems failed: \${result.status}\`)
|
|
152
162
|
return result.data as unknown[]
|
|
153
163
|
},
|
|
154
164
|
|
|
155
165
|
async getItem(itemId: string): Promise<unknown> {
|
|
156
|
-
const result = await fetch(\`\${API_BASE_URL}/items/\${itemId}\`, {
|
|
166
|
+
const result = await fetch(\`\${API_BASE_URL}/items/\${itemId}\`, {
|
|
167
|
+
method: 'GET',
|
|
168
|
+
headers: {
|
|
169
|
+
'X-API-Key': '{{settings.apiKey}}',
|
|
170
|
+
},
|
|
171
|
+
})
|
|
157
172
|
if (!result.ok) throw new Error(\`getItem failed: \${result.status}\`)
|
|
158
173
|
return result.data as unknown
|
|
159
174
|
},
|
|
@@ -180,12 +195,13 @@ export const appStore = createStore<AppState>({
|
|
|
180
195
|
{
|
|
181
196
|
path: "surfaces/Content.tsx",
|
|
182
197
|
title: "Current Content Surface",
|
|
183
|
-
code: `import { ui, useStore, useContextData, Surface } from '@stackable-labs/sdk-extension-react'
|
|
198
|
+
code: `import { ui, useStore, useContextData, useSettings, Surface } from '@stackable-labs/sdk-extension-react'
|
|
184
199
|
import { appStore } from '../store'
|
|
185
200
|
|
|
186
201
|
export function Content() {
|
|
187
202
|
const viewState = useStore(appStore, (s) => s.viewState)
|
|
188
203
|
const { loading } = useContextData()
|
|
204
|
+
const settings = useSettings() // Non-secret settings from settingsSchema
|
|
189
205
|
|
|
190
206
|
if (loading) {
|
|
191
207
|
return (
|
|
@@ -249,19 +265,33 @@ export function createApi(query: QueryFn) {
|
|
|
249
265
|
}
|
|
250
266
|
|
|
251
267
|
// \u2500\u2500 data.fetch wrapper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
268
|
+
//
|
|
269
|
+
// For API keys and secrets, use {{settings.xxx}} placeholders in headers.
|
|
270
|
+
// The proxy resolves them server-side \u2014 the real secret never enters extension code.
|
|
271
|
+
// Declare secret fields in manifest.json settingsSchema with "secret": true.
|
|
252
272
|
|
|
253
273
|
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL as string
|
|
254
274
|
|
|
255
275
|
export function createFetchApi(fetch: FetchFn) {
|
|
256
276
|
return {
|
|
257
277
|
async getItems(): Promise<unknown[]> {
|
|
258
|
-
const result = await fetch(\`\${API_BASE_URL}/items\`, {
|
|
278
|
+
const result = await fetch(\`\${API_BASE_URL}/items\`, {
|
|
279
|
+
method: 'GET',
|
|
280
|
+
headers: {
|
|
281
|
+
'X-API-Key': '{{settings.apiKey}}',
|
|
282
|
+
},
|
|
283
|
+
})
|
|
259
284
|
if (!result.ok) throw new Error(\`getItems failed: \${result.status}\`)
|
|
260
285
|
return result.data as unknown[]
|
|
261
286
|
},
|
|
262
287
|
|
|
263
288
|
async getItem(itemId: string): Promise<unknown> {
|
|
264
|
-
const result = await fetch(\`\${API_BASE_URL}/items/\${itemId}\`, {
|
|
289
|
+
const result = await fetch(\`\${API_BASE_URL}/items/\${itemId}\`, {
|
|
290
|
+
method: 'GET',
|
|
291
|
+
headers: {
|
|
292
|
+
'X-API-Key': '{{settings.apiKey}}',
|
|
293
|
+
},
|
|
294
|
+
})
|
|
265
295
|
if (!result.ok) throw new Error(\`getItem failed: \${result.status}\`)
|
|
266
296
|
return result.data as unknown
|
|
267
297
|
},
|
|
@@ -3680,8 +3710,11 @@ var CAPABILITY_SNIPPETS2 = {
|
|
|
3680
3710
|
const result = await capabilities.data.query({ path: '/your-endpoint', method: 'GET' })`,
|
|
3681
3711
|
"data.fetch": `const capabilities = useCapabilities()
|
|
3682
3712
|
const response = await capabilities.data.fetch('https://api.example.com/endpoint')`,
|
|
3683
|
-
"context.read":
|
|
3684
|
-
const
|
|
3713
|
+
"context.read": `// Read host context + extension settings
|
|
3714
|
+
const { customerId, settings } = useContextData()
|
|
3715
|
+
|
|
3716
|
+
// Or use the convenience hook for settings only
|
|
3717
|
+
const settings = useSettings()`,
|
|
3685
3718
|
"actions.toast": `const capabilities = useCapabilities()
|
|
3686
3719
|
capabilities.actions.toast({ type: 'success', message: 'Done!' })`,
|
|
3687
3720
|
"actions.invoke": `const capabilities = useCapabilities()
|