@contractspec/example.integration-hub 3.7.5 → 3.7.7

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/ui/index.js CHANGED
@@ -1,127 +1,540 @@
1
1
  // @bun
2
- // src/ui/renderers/integration.markdown.ts
3
- var mockIntegrations = [
4
- {
5
- id: "int-1",
6
- name: "Salesforce",
7
- type: "CRM",
8
- status: "ACTIVE",
9
- connectionCount: 3
10
- },
11
- {
12
- id: "int-2",
13
- name: "HubSpot",
14
- type: "MARKETING",
15
- status: "ACTIVE",
16
- connectionCount: 2
17
- },
18
- {
19
- id: "int-3",
20
- name: "Stripe",
21
- type: "PAYMENT",
22
- status: "ACTIVE",
23
- connectionCount: 1
24
- },
25
- {
26
- id: "int-4",
27
- name: "Slack",
28
- type: "COMMUNICATION",
29
- status: "INACTIVE",
30
- connectionCount: 0
31
- },
32
- {
33
- id: "int-5",
34
- name: "Google Sheets",
35
- type: "DATA",
36
- status: "ACTIVE",
37
- connectionCount: 5
38
- },
39
- {
40
- id: "int-6",
41
- name: "PostHog",
42
- type: "ANALYTICS",
43
- status: "ACTIVE",
44
- connectionCount: 1
45
- }
2
+ // src/ui/hooks/useIntegrationData.ts
3
+ import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
4
+ import { useCallback, useEffect, useState } from "react";
5
+ "use client";
6
+ function useIntegrationData(projectId = "local-project") {
7
+ const { handlers } = useTemplateRuntime();
8
+ const integration = handlers.integration;
9
+ const [integrations, setIntegrations] = useState([]);
10
+ const [connections, setConnections] = useState([]);
11
+ const [syncConfigs, setSyncConfigs] = useState([]);
12
+ const [loading, setLoading] = useState(true);
13
+ const [error, setError] = useState(null);
14
+ const fetchData = useCallback(async () => {
15
+ try {
16
+ setLoading(true);
17
+ setError(null);
18
+ const [integResult, connResult, syncResult] = await Promise.all([
19
+ integration.listIntegrations({ projectId, limit: 100 }),
20
+ integration.listConnections({ limit: 100 }),
21
+ integration.listSyncConfigs({ limit: 100 })
22
+ ]);
23
+ setIntegrations(integResult.integrations);
24
+ setConnections(connResult.connections);
25
+ setSyncConfigs(syncResult.configs);
26
+ } catch (err) {
27
+ setError(err instanceof Error ? err : new Error("Failed to load integrations"));
28
+ } finally {
29
+ setLoading(false);
30
+ }
31
+ }, [integration, projectId]);
32
+ useEffect(() => {
33
+ fetchData();
34
+ }, [fetchData]);
35
+ const stats = {
36
+ totalIntegrations: integrations.length,
37
+ activeIntegrations: integrations.filter((i) => i.status === "ACTIVE").length,
38
+ totalConnections: connections.length,
39
+ connectedCount: connections.filter((c) => c.status === "CONNECTED").length,
40
+ totalSyncs: syncConfigs.length,
41
+ activeSyncs: syncConfigs.filter((s) => s.status === "ACTIVE").length
42
+ };
43
+ return {
44
+ integrations,
45
+ connections,
46
+ syncConfigs,
47
+ loading,
48
+ error,
49
+ stats,
50
+ refetch: fetchData
51
+ };
52
+ }
53
+
54
+ // src/ui/hooks/index.ts
55
+ "use client";
56
+
57
+ // src/ui/IntegrationHubChat.tsx
58
+ import { ChatWithSidebar } from "@contractspec/module.ai-chat";
59
+ import { jsxDEV } from "react/jsx-dev-runtime";
60
+ "use client";
61
+ var DEFAULT_SUGGESTIONS = [
62
+ "List my integrations",
63
+ "Show sync status",
64
+ "Add a connection"
46
65
  ];
47
- var mockConnections = [
48
- {
49
- id: "conn-1",
50
- integrationId: "int-1",
51
- name: "Production Salesforce",
52
- status: "CONNECTED",
53
- lastSyncAt: "2024-01-16T10:00:00Z"
54
- },
55
- {
56
- id: "conn-2",
57
- integrationId: "int-1",
58
- name: "Sandbox Salesforce",
59
- status: "CONNECTED",
60
- lastSyncAt: "2024-01-15T14:00:00Z"
61
- },
62
- {
63
- id: "conn-3",
64
- integrationId: "int-2",
65
- name: "Marketing HubSpot",
66
- status: "CONNECTED",
67
- lastSyncAt: "2024-01-16T08:00:00Z"
68
- },
69
- {
70
- id: "conn-4",
71
- integrationId: "int-3",
72
- name: "Stripe Live",
73
- status: "CONNECTED",
74
- lastSyncAt: "2024-01-16T12:00:00Z"
75
- },
76
- {
77
- id: "conn-5",
78
- integrationId: "int-5",
79
- name: "Analytics Sheet",
80
- status: "ERROR",
81
- lastSyncAt: "2024-01-14T09:00:00Z",
82
- error: "Authentication expired"
83
- },
84
- {
85
- id: "conn-6",
86
- integrationId: "int-6",
87
- name: "PostHog Workspace",
88
- status: "CONNECTED",
89
- lastSyncAt: "2024-01-16T11:45:00Z"
66
+ var DEFAULT_SYSTEM_PROMPT = `You are an Integration Hub assistant. Help users manage integrations, connections, and sync configurations. When asked about integrations, connections, or syncs, provide clear, actionable guidance.`;
67
+ function IntegrationHubChat({
68
+ proxyUrl = "/api/chat",
69
+ mcpServers,
70
+ thinkingLevel = "thinking",
71
+ suggestions = DEFAULT_SUGGESTIONS,
72
+ systemPrompt = DEFAULT_SYSTEM_PROMPT,
73
+ className
74
+ }) {
75
+ return /* @__PURE__ */ jsxDEV("div", {
76
+ className: className ?? "flex h-[500px] flex-col",
77
+ children: /* @__PURE__ */ jsxDEV(ChatWithSidebar, {
78
+ className: "flex-1",
79
+ systemPrompt,
80
+ proxyUrl,
81
+ mcpServers,
82
+ thinkingLevel,
83
+ suggestions,
84
+ showSuggestionsWhenEmpty: true
85
+ }, undefined, false, undefined, this)
86
+ }, undefined, false, undefined, this);
87
+ }
88
+
89
+ // src/ui/IntegrationDashboard.tsx
90
+ import {
91
+ Button,
92
+ ErrorState,
93
+ LoaderBlock,
94
+ StatCard,
95
+ StatCardGroup
96
+ } from "@contractspec/lib.design-system";
97
+ import { useState as useState2 } from "react";
98
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
99
+ "use client";
100
+ var STATUS_COLORS = {
101
+ ACTIVE: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",
102
+ INACTIVE: "bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400",
103
+ CONNECTED: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",
104
+ DISCONNECTED: "bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400",
105
+ PENDING: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400",
106
+ ERROR: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",
107
+ PAUSED: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400"
108
+ };
109
+ var TYPE_ICONS = {
110
+ CRM: "\uD83D\uDCCA",
111
+ MARKETING: "\uD83D\uDCE3",
112
+ PAYMENT: "\uD83D\uDCB3",
113
+ COMMUNICATION: "\uD83D\uDCAC",
114
+ DATA: "\uD83D\uDDC4\uFE0F",
115
+ CUSTOM: "\u2699\uFE0F"
116
+ };
117
+ function IntegrationDashboard() {
118
+ const [activeTab, setActiveTab] = useState2("integrations");
119
+ const {
120
+ integrations,
121
+ connections,
122
+ syncConfigs,
123
+ loading,
124
+ error,
125
+ stats,
126
+ refetch
127
+ } = useIntegrationData();
128
+ const tabs = [
129
+ { id: "integrations", label: "Integrations", icon: "\uD83D\uDD0C" },
130
+ { id: "connections", label: "Connections", icon: "\uD83D\uDD17" },
131
+ { id: "syncs", label: "Sync Configs", icon: "\uD83D\uDD04" },
132
+ { id: "chat", label: "Chat", icon: "\uD83D\uDCAC" }
133
+ ];
134
+ if (loading) {
135
+ return /* @__PURE__ */ jsxDEV2(LoaderBlock, {
136
+ label: "Loading Integrations..."
137
+ }, undefined, false, undefined, this);
90
138
  }
91
- ];
92
- var mockSyncConfigs = [
93
- {
94
- id: "sync-1",
95
- connectionId: "conn-1",
96
- name: "Contacts Sync",
97
- frequency: "HOURLY",
98
- lastRunAt: "2024-01-16T10:00:00Z",
99
- status: "SUCCESS",
100
- recordsSynced: 1250
101
- },
102
- {
103
- id: "sync-2",
104
- connectionId: "conn-1",
105
- name: "Opportunities Sync",
106
- frequency: "DAILY",
107
- lastRunAt: "2024-01-16T00:00:00Z",
108
- status: "SUCCESS",
109
- recordsSynced: 340
110
- },
111
- {
112
- id: "sync-3",
113
- connectionId: "conn-3",
114
- name: "Orders Sync",
115
- frequency: "REALTIME",
116
- lastRunAt: "2024-01-16T12:30:00Z",
117
- status: "SUCCESS",
118
- recordsSynced: 89
119
- },
120
- {
121
- id: "sync-4",
122
- connectionId: "conn-5",
123
- name: "Metrics Export",
124
- frequency: "DAILY",
139
+ if (error) {
140
+ return /* @__PURE__ */ jsxDEV2(ErrorState, {
141
+ title: "Failed to load Integrations",
142
+ description: error.message,
143
+ onRetry: refetch,
144
+ retryLabel: "Retry"
145
+ }, undefined, false, undefined, this);
146
+ }
147
+ return /* @__PURE__ */ jsxDEV2("div", {
148
+ className: "space-y-6",
149
+ children: [
150
+ /* @__PURE__ */ jsxDEV2("div", {
151
+ className: "flex items-center justify-between",
152
+ children: [
153
+ /* @__PURE__ */ jsxDEV2("h2", {
154
+ className: "font-bold text-2xl",
155
+ children: "Integration Hub"
156
+ }, undefined, false, undefined, this),
157
+ /* @__PURE__ */ jsxDEV2(Button, {
158
+ onClick: () => alert("Add integration modal"),
159
+ children: [
160
+ /* @__PURE__ */ jsxDEV2("span", {
161
+ className: "mr-2",
162
+ children: "+"
163
+ }, undefined, false, undefined, this),
164
+ " Add Integration"
165
+ ]
166
+ }, undefined, true, undefined, this)
167
+ ]
168
+ }, undefined, true, undefined, this),
169
+ /* @__PURE__ */ jsxDEV2(StatCardGroup, {
170
+ children: [
171
+ /* @__PURE__ */ jsxDEV2(StatCard, {
172
+ label: "Integrations",
173
+ value: stats.totalIntegrations,
174
+ hint: `${stats.activeIntegrations} active`
175
+ }, undefined, false, undefined, this),
176
+ /* @__PURE__ */ jsxDEV2(StatCard, {
177
+ label: "Connections",
178
+ value: stats.totalConnections,
179
+ hint: `${stats.connectedCount} connected`
180
+ }, undefined, false, undefined, this),
181
+ /* @__PURE__ */ jsxDEV2(StatCard, {
182
+ label: "Syncs",
183
+ value: stats.totalSyncs,
184
+ hint: `${stats.activeSyncs} active`
185
+ }, undefined, false, undefined, this)
186
+ ]
187
+ }, undefined, true, undefined, this),
188
+ /* @__PURE__ */ jsxDEV2("nav", {
189
+ className: "flex gap-1 rounded-lg bg-muted p-1",
190
+ role: "tablist",
191
+ children: tabs.map((tab) => /* @__PURE__ */ jsxDEV2(Button, {
192
+ type: "button",
193
+ role: "tab",
194
+ "aria-selected": activeTab === tab.id,
195
+ onClick: () => setActiveTab(tab.id),
196
+ className: `flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 font-medium text-sm transition-colors ${activeTab === tab.id ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
197
+ children: [
198
+ /* @__PURE__ */ jsxDEV2("span", {
199
+ children: tab.icon
200
+ }, undefined, false, undefined, this),
201
+ tab.label
202
+ ]
203
+ }, tab.id, true, undefined, this))
204
+ }, undefined, false, undefined, this),
205
+ /* @__PURE__ */ jsxDEV2("div", {
206
+ className: "min-h-[400px]",
207
+ role: "tabpanel",
208
+ children: [
209
+ activeTab === "integrations" && /* @__PURE__ */ jsxDEV2("div", {
210
+ className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3",
211
+ children: [
212
+ integrations.map((integration) => /* @__PURE__ */ jsxDEV2("div", {
213
+ className: "cursor-pointer rounded-lg border border-border bg-card p-4 transition-colors hover:bg-muted/50",
214
+ children: [
215
+ /* @__PURE__ */ jsxDEV2("div", {
216
+ className: "mb-3 flex items-center gap-3",
217
+ children: [
218
+ /* @__PURE__ */ jsxDEV2("span", {
219
+ className: "text-2xl",
220
+ children: TYPE_ICONS[integration.type] ?? "\u2699\uFE0F"
221
+ }, undefined, false, undefined, this),
222
+ /* @__PURE__ */ jsxDEV2("div", {
223
+ children: [
224
+ /* @__PURE__ */ jsxDEV2("h3", {
225
+ className: "font-medium",
226
+ children: integration.name
227
+ }, undefined, false, undefined, this),
228
+ /* @__PURE__ */ jsxDEV2("p", {
229
+ className: "text-muted-foreground text-sm",
230
+ children: integration.type
231
+ }, undefined, false, undefined, this)
232
+ ]
233
+ }, undefined, true, undefined, this)
234
+ ]
235
+ }, undefined, true, undefined, this),
236
+ /* @__PURE__ */ jsxDEV2("div", {
237
+ className: "flex items-center justify-between",
238
+ children: [
239
+ /* @__PURE__ */ jsxDEV2("span", {
240
+ className: `inline-flex rounded-full px-2 py-0.5 font-medium text-xs ${STATUS_COLORS[integration.status] ?? ""}`,
241
+ children: integration.status
242
+ }, undefined, false, undefined, this),
243
+ /* @__PURE__ */ jsxDEV2("span", {
244
+ className: "text-muted-foreground text-xs",
245
+ children: integration.createdAt.toLocaleDateString()
246
+ }, undefined, false, undefined, this)
247
+ ]
248
+ }, undefined, true, undefined, this)
249
+ ]
250
+ }, integration.id, true, undefined, this)),
251
+ integrations.length === 0 && /* @__PURE__ */ jsxDEV2("div", {
252
+ className: "col-span-full flex h-64 items-center justify-center text-muted-foreground",
253
+ children: "No integrations configured"
254
+ }, undefined, false, undefined, this)
255
+ ]
256
+ }, undefined, true, undefined, this),
257
+ activeTab === "connections" && /* @__PURE__ */ jsxDEV2("div", {
258
+ className: "rounded-lg border border-border",
259
+ children: /* @__PURE__ */ jsxDEV2("table", {
260
+ className: "w-full",
261
+ children: [
262
+ /* @__PURE__ */ jsxDEV2("thead", {
263
+ className: "border-border border-b bg-muted/30",
264
+ children: /* @__PURE__ */ jsxDEV2("tr", {
265
+ children: [
266
+ /* @__PURE__ */ jsxDEV2("th", {
267
+ className: "px-4 py-3 text-left font-medium text-sm",
268
+ children: "Connection"
269
+ }, undefined, false, undefined, this),
270
+ /* @__PURE__ */ jsxDEV2("th", {
271
+ className: "px-4 py-3 text-left font-medium text-sm",
272
+ children: "Status"
273
+ }, undefined, false, undefined, this),
274
+ /* @__PURE__ */ jsxDEV2("th", {
275
+ className: "px-4 py-3 text-left font-medium text-sm",
276
+ children: "Last Sync"
277
+ }, undefined, false, undefined, this)
278
+ ]
279
+ }, undefined, true, undefined, this)
280
+ }, undefined, false, undefined, this),
281
+ /* @__PURE__ */ jsxDEV2("tbody", {
282
+ className: "divide-y divide-border",
283
+ children: [
284
+ connections.map((conn) => /* @__PURE__ */ jsxDEV2("tr", {
285
+ className: "hover:bg-muted/50",
286
+ children: [
287
+ /* @__PURE__ */ jsxDEV2("td", {
288
+ className: "px-4 py-3",
289
+ children: /* @__PURE__ */ jsxDEV2("div", {
290
+ className: "font-medium",
291
+ children: conn.name
292
+ }, undefined, false, undefined, this)
293
+ }, undefined, false, undefined, this),
294
+ /* @__PURE__ */ jsxDEV2("td", {
295
+ className: "px-4 py-3",
296
+ children: /* @__PURE__ */ jsxDEV2("span", {
297
+ className: `inline-flex rounded-full px-2 py-0.5 font-medium text-xs ${STATUS_COLORS[conn.status] ?? ""}`,
298
+ children: conn.status
299
+ }, undefined, false, undefined, this)
300
+ }, undefined, false, undefined, this),
301
+ /* @__PURE__ */ jsxDEV2("td", {
302
+ className: "px-4 py-3 text-muted-foreground text-sm",
303
+ children: conn.lastSyncAt?.toLocaleString() ?? "Never"
304
+ }, undefined, false, undefined, this)
305
+ ]
306
+ }, conn.id, true, undefined, this)),
307
+ connections.length === 0 && /* @__PURE__ */ jsxDEV2("tr", {
308
+ children: /* @__PURE__ */ jsxDEV2("td", {
309
+ colSpan: 3,
310
+ className: "px-4 py-8 text-center text-muted-foreground",
311
+ children: "No connections found"
312
+ }, undefined, false, undefined, this)
313
+ }, undefined, false, undefined, this)
314
+ ]
315
+ }, undefined, true, undefined, this)
316
+ ]
317
+ }, undefined, true, undefined, this)
318
+ }, undefined, false, undefined, this),
319
+ activeTab === "chat" && /* @__PURE__ */ jsxDEV2(IntegrationHubChat, {
320
+ proxyUrl: "/api/chat",
321
+ thinkingLevel: "thinking",
322
+ suggestions: [
323
+ "List my integrations",
324
+ "Show sync status",
325
+ "Add a connection"
326
+ ],
327
+ className: "min-h-[400px]"
328
+ }, undefined, false, undefined, this),
329
+ activeTab === "syncs" && /* @__PURE__ */ jsxDEV2("div", {
330
+ className: "rounded-lg border border-border",
331
+ children: /* @__PURE__ */ jsxDEV2("table", {
332
+ className: "w-full",
333
+ children: [
334
+ /* @__PURE__ */ jsxDEV2("thead", {
335
+ className: "border-border border-b bg-muted/30",
336
+ children: /* @__PURE__ */ jsxDEV2("tr", {
337
+ children: [
338
+ /* @__PURE__ */ jsxDEV2("th", {
339
+ className: "px-4 py-3 text-left font-medium text-sm",
340
+ children: "Sync Config"
341
+ }, undefined, false, undefined, this),
342
+ /* @__PURE__ */ jsxDEV2("th", {
343
+ className: "px-4 py-3 text-left font-medium text-sm",
344
+ children: "Frequency"
345
+ }, undefined, false, undefined, this),
346
+ /* @__PURE__ */ jsxDEV2("th", {
347
+ className: "px-4 py-3 text-left font-medium text-sm",
348
+ children: "Status"
349
+ }, undefined, false, undefined, this),
350
+ /* @__PURE__ */ jsxDEV2("th", {
351
+ className: "px-4 py-3 text-left font-medium text-sm",
352
+ children: "Records"
353
+ }, undefined, false, undefined, this)
354
+ ]
355
+ }, undefined, true, undefined, this)
356
+ }, undefined, false, undefined, this),
357
+ /* @__PURE__ */ jsxDEV2("tbody", {
358
+ className: "divide-y divide-border",
359
+ children: [
360
+ syncConfigs.map((sync) => /* @__PURE__ */ jsxDEV2("tr", {
361
+ className: "hover:bg-muted/50",
362
+ children: [
363
+ /* @__PURE__ */ jsxDEV2("td", {
364
+ className: "px-4 py-3",
365
+ children: [
366
+ /* @__PURE__ */ jsxDEV2("div", {
367
+ className: "font-medium",
368
+ children: sync.name
369
+ }, undefined, false, undefined, this),
370
+ /* @__PURE__ */ jsxDEV2("div", {
371
+ className: "text-muted-foreground text-sm",
372
+ children: [
373
+ sync.sourceEntity,
374
+ " \u2192 ",
375
+ sync.targetEntity
376
+ ]
377
+ }, undefined, true, undefined, this)
378
+ ]
379
+ }, undefined, true, undefined, this),
380
+ /* @__PURE__ */ jsxDEV2("td", {
381
+ className: "px-4 py-3 text-sm",
382
+ children: sync.frequency
383
+ }, undefined, false, undefined, this),
384
+ /* @__PURE__ */ jsxDEV2("td", {
385
+ className: "px-4 py-3",
386
+ children: /* @__PURE__ */ jsxDEV2("span", {
387
+ className: `inline-flex rounded-full px-2 py-0.5 font-medium text-xs ${STATUS_COLORS[sync.status] ?? ""}`,
388
+ children: sync.status
389
+ }, undefined, false, undefined, this)
390
+ }, undefined, false, undefined, this),
391
+ /* @__PURE__ */ jsxDEV2("td", {
392
+ className: "px-4 py-3 text-muted-foreground text-sm",
393
+ children: sync.recordsSynced.toLocaleString()
394
+ }, undefined, false, undefined, this)
395
+ ]
396
+ }, sync.id, true, undefined, this)),
397
+ syncConfigs.length === 0 && /* @__PURE__ */ jsxDEV2("tr", {
398
+ children: /* @__PURE__ */ jsxDEV2("td", {
399
+ colSpan: 4,
400
+ className: "px-4 py-8 text-center text-muted-foreground",
401
+ children: "No sync configurations found"
402
+ }, undefined, false, undefined, this)
403
+ }, undefined, false, undefined, this)
404
+ ]
405
+ }, undefined, true, undefined, this)
406
+ ]
407
+ }, undefined, true, undefined, this)
408
+ }, undefined, false, undefined, this)
409
+ ]
410
+ }, undefined, true, undefined, this)
411
+ ]
412
+ }, undefined, true, undefined, this);
413
+ }
414
+
415
+ // src/ui/renderers/integration.markdown.ts
416
+ var mockIntegrations = [
417
+ {
418
+ id: "int-1",
419
+ name: "Salesforce",
420
+ type: "CRM",
421
+ status: "ACTIVE",
422
+ connectionCount: 3
423
+ },
424
+ {
425
+ id: "int-2",
426
+ name: "HubSpot",
427
+ type: "MARKETING",
428
+ status: "ACTIVE",
429
+ connectionCount: 2
430
+ },
431
+ {
432
+ id: "int-3",
433
+ name: "Stripe",
434
+ type: "PAYMENT",
435
+ status: "ACTIVE",
436
+ connectionCount: 1
437
+ },
438
+ {
439
+ id: "int-4",
440
+ name: "Slack",
441
+ type: "COMMUNICATION",
442
+ status: "INACTIVE",
443
+ connectionCount: 0
444
+ },
445
+ {
446
+ id: "int-5",
447
+ name: "Google Sheets",
448
+ type: "DATA",
449
+ status: "ACTIVE",
450
+ connectionCount: 5
451
+ },
452
+ {
453
+ id: "int-6",
454
+ name: "PostHog",
455
+ type: "ANALYTICS",
456
+ status: "ACTIVE",
457
+ connectionCount: 1
458
+ }
459
+ ];
460
+ var mockConnections = [
461
+ {
462
+ id: "conn-1",
463
+ integrationId: "int-1",
464
+ name: "Production Salesforce",
465
+ status: "CONNECTED",
466
+ lastSyncAt: "2024-01-16T10:00:00Z"
467
+ },
468
+ {
469
+ id: "conn-2",
470
+ integrationId: "int-1",
471
+ name: "Sandbox Salesforce",
472
+ status: "CONNECTED",
473
+ lastSyncAt: "2024-01-15T14:00:00Z"
474
+ },
475
+ {
476
+ id: "conn-3",
477
+ integrationId: "int-2",
478
+ name: "Marketing HubSpot",
479
+ status: "CONNECTED",
480
+ lastSyncAt: "2024-01-16T08:00:00Z"
481
+ },
482
+ {
483
+ id: "conn-4",
484
+ integrationId: "int-3",
485
+ name: "Stripe Live",
486
+ status: "CONNECTED",
487
+ lastSyncAt: "2024-01-16T12:00:00Z"
488
+ },
489
+ {
490
+ id: "conn-5",
491
+ integrationId: "int-5",
492
+ name: "Analytics Sheet",
493
+ status: "ERROR",
494
+ lastSyncAt: "2024-01-14T09:00:00Z",
495
+ error: "Authentication expired"
496
+ },
497
+ {
498
+ id: "conn-6",
499
+ integrationId: "int-6",
500
+ name: "PostHog Workspace",
501
+ status: "CONNECTED",
502
+ lastSyncAt: "2024-01-16T11:45:00Z"
503
+ }
504
+ ];
505
+ var mockSyncConfigs = [
506
+ {
507
+ id: "sync-1",
508
+ connectionId: "conn-1",
509
+ name: "Contacts Sync",
510
+ frequency: "HOURLY",
511
+ lastRunAt: "2024-01-16T10:00:00Z",
512
+ status: "SUCCESS",
513
+ recordsSynced: 1250
514
+ },
515
+ {
516
+ id: "sync-2",
517
+ connectionId: "conn-1",
518
+ name: "Opportunities Sync",
519
+ frequency: "DAILY",
520
+ lastRunAt: "2024-01-16T00:00:00Z",
521
+ status: "SUCCESS",
522
+ recordsSynced: 340
523
+ },
524
+ {
525
+ id: "sync-3",
526
+ connectionId: "conn-3",
527
+ name: "Orders Sync",
528
+ frequency: "REALTIME",
529
+ lastRunAt: "2024-01-16T12:30:00Z",
530
+ status: "SUCCESS",
531
+ recordsSynced: 89
532
+ },
533
+ {
534
+ id: "sync-4",
535
+ connectionId: "conn-5",
536
+ name: "Metrics Export",
537
+ frequency: "DAILY",
125
538
  lastRunAt: "2024-01-14T09:00:00Z",
126
539
  status: "FAILED",
127
540
  recordsSynced: 0
@@ -255,430 +668,18 @@ var syncConfigMarkdownRenderer = {
255
668
  }
256
669
  lines.push("## Frequency Options");
257
670
  lines.push("");
258
- lines.push("- **REALTIME**: Sync on every change");
259
- lines.push("- **HOURLY**: Sync every hour");
260
- lines.push("- **DAILY**: Sync once per day");
261
- lines.push("- **WEEKLY**: Sync once per week");
262
- lines.push("- **MANUAL**: Sync only when triggered");
263
- return {
264
- mimeType: "text/markdown",
265
- body: lines.join(`
266
- `)
267
- };
268
- }
269
- };
270
- // src/ui/hooks/useIntegrationData.ts
271
- import { useCallback, useEffect, useState } from "react";
272
- import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
273
- "use client";
274
- function useIntegrationData(projectId = "local-project") {
275
- const { handlers } = useTemplateRuntime();
276
- const integration = handlers.integration;
277
- const [integrations, setIntegrations] = useState([]);
278
- const [connections, setConnections] = useState([]);
279
- const [syncConfigs, setSyncConfigs] = useState([]);
280
- const [loading, setLoading] = useState(true);
281
- const [error, setError] = useState(null);
282
- const fetchData = useCallback(async () => {
283
- try {
284
- setLoading(true);
285
- setError(null);
286
- const [integResult, connResult, syncResult] = await Promise.all([
287
- integration.listIntegrations({ projectId, limit: 100 }),
288
- integration.listConnections({ limit: 100 }),
289
- integration.listSyncConfigs({ limit: 100 })
290
- ]);
291
- setIntegrations(integResult.integrations);
292
- setConnections(connResult.connections);
293
- setSyncConfigs(syncResult.configs);
294
- } catch (err) {
295
- setError(err instanceof Error ? err : new Error("Failed to load integrations"));
296
- } finally {
297
- setLoading(false);
298
- }
299
- }, [integration, projectId]);
300
- useEffect(() => {
301
- fetchData();
302
- }, [fetchData]);
303
- const stats = {
304
- totalIntegrations: integrations.length,
305
- activeIntegrations: integrations.filter((i) => i.status === "ACTIVE").length,
306
- totalConnections: connections.length,
307
- connectedCount: connections.filter((c) => c.status === "CONNECTED").length,
308
- totalSyncs: syncConfigs.length,
309
- activeSyncs: syncConfigs.filter((s) => s.status === "ACTIVE").length
310
- };
311
- return {
312
- integrations,
313
- connections,
314
- syncConfigs,
315
- loading,
316
- error,
317
- stats,
318
- refetch: fetchData
319
- };
320
- }
321
-
322
- // src/ui/IntegrationHubChat.tsx
323
- import { ChatWithSidebar } from "@contractspec/module.ai-chat";
324
- import { jsxDEV } from "react/jsx-dev-runtime";
325
- "use client";
326
- var DEFAULT_SUGGESTIONS = [
327
- "List my integrations",
328
- "Show sync status",
329
- "Add a connection"
330
- ];
331
- var DEFAULT_SYSTEM_PROMPT = `You are an Integration Hub assistant. Help users manage integrations, connections, and sync configurations. When asked about integrations, connections, or syncs, provide clear, actionable guidance.`;
332
- function IntegrationHubChat({
333
- proxyUrl = "/api/chat",
334
- mcpServers,
335
- thinkingLevel = "thinking",
336
- suggestions = DEFAULT_SUGGESTIONS,
337
- systemPrompt = DEFAULT_SYSTEM_PROMPT,
338
- className
339
- }) {
340
- return /* @__PURE__ */ jsxDEV("div", {
341
- className: className ?? "flex h-[500px] flex-col",
342
- children: /* @__PURE__ */ jsxDEV(ChatWithSidebar, {
343
- className: "flex-1",
344
- systemPrompt,
345
- proxyUrl,
346
- mcpServers,
347
- thinkingLevel,
348
- suggestions,
349
- showSuggestionsWhenEmpty: true
350
- }, undefined, false, undefined, this)
351
- }, undefined, false, undefined, this);
352
- }
353
-
354
- // src/ui/IntegrationDashboard.tsx
355
- import { useState as useState2 } from "react";
356
- import {
357
- Button,
358
- ErrorState,
359
- LoaderBlock,
360
- StatCard,
361
- StatCardGroup
362
- } from "@contractspec/lib.design-system";
363
- import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
364
- "use client";
365
- var STATUS_COLORS = {
366
- ACTIVE: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",
367
- INACTIVE: "bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400",
368
- CONNECTED: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",
369
- DISCONNECTED: "bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400",
370
- PENDING: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400",
371
- ERROR: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",
372
- PAUSED: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400"
373
- };
374
- var TYPE_ICONS = {
375
- CRM: "\uD83D\uDCCA",
376
- MARKETING: "\uD83D\uDCE3",
377
- PAYMENT: "\uD83D\uDCB3",
378
- COMMUNICATION: "\uD83D\uDCAC",
379
- DATA: "\uD83D\uDDC4\uFE0F",
380
- CUSTOM: "\u2699\uFE0F"
381
- };
382
- function IntegrationDashboard() {
383
- const [activeTab, setActiveTab] = useState2("integrations");
384
- const {
385
- integrations,
386
- connections,
387
- syncConfigs,
388
- loading,
389
- error,
390
- stats,
391
- refetch
392
- } = useIntegrationData();
393
- const tabs = [
394
- { id: "integrations", label: "Integrations", icon: "\uD83D\uDD0C" },
395
- { id: "connections", label: "Connections", icon: "\uD83D\uDD17" },
396
- { id: "syncs", label: "Sync Configs", icon: "\uD83D\uDD04" },
397
- { id: "chat", label: "Chat", icon: "\uD83D\uDCAC" }
398
- ];
399
- if (loading) {
400
- return /* @__PURE__ */ jsxDEV2(LoaderBlock, {
401
- label: "Loading Integrations..."
402
- }, undefined, false, undefined, this);
403
- }
404
- if (error) {
405
- return /* @__PURE__ */ jsxDEV2(ErrorState, {
406
- title: "Failed to load Integrations",
407
- description: error.message,
408
- onRetry: refetch,
409
- retryLabel: "Retry"
410
- }, undefined, false, undefined, this);
671
+ lines.push("- **REALTIME**: Sync on every change");
672
+ lines.push("- **HOURLY**: Sync every hour");
673
+ lines.push("- **DAILY**: Sync once per day");
674
+ lines.push("- **WEEKLY**: Sync once per week");
675
+ lines.push("- **MANUAL**: Sync only when triggered");
676
+ return {
677
+ mimeType: "text/markdown",
678
+ body: lines.join(`
679
+ `)
680
+ };
411
681
  }
412
- return /* @__PURE__ */ jsxDEV2("div", {
413
- className: "space-y-6",
414
- children: [
415
- /* @__PURE__ */ jsxDEV2("div", {
416
- className: "flex items-center justify-between",
417
- children: [
418
- /* @__PURE__ */ jsxDEV2("h2", {
419
- className: "text-2xl font-bold",
420
- children: "Integration Hub"
421
- }, undefined, false, undefined, this),
422
- /* @__PURE__ */ jsxDEV2(Button, {
423
- onClick: () => alert("Add integration modal"),
424
- children: [
425
- /* @__PURE__ */ jsxDEV2("span", {
426
- className: "mr-2",
427
- children: "+"
428
- }, undefined, false, undefined, this),
429
- " Add Integration"
430
- ]
431
- }, undefined, true, undefined, this)
432
- ]
433
- }, undefined, true, undefined, this),
434
- /* @__PURE__ */ jsxDEV2(StatCardGroup, {
435
- children: [
436
- /* @__PURE__ */ jsxDEV2(StatCard, {
437
- label: "Integrations",
438
- value: stats.totalIntegrations,
439
- hint: `${stats.activeIntegrations} active`
440
- }, undefined, false, undefined, this),
441
- /* @__PURE__ */ jsxDEV2(StatCard, {
442
- label: "Connections",
443
- value: stats.totalConnections,
444
- hint: `${stats.connectedCount} connected`
445
- }, undefined, false, undefined, this),
446
- /* @__PURE__ */ jsxDEV2(StatCard, {
447
- label: "Syncs",
448
- value: stats.totalSyncs,
449
- hint: `${stats.activeSyncs} active`
450
- }, undefined, false, undefined, this)
451
- ]
452
- }, undefined, true, undefined, this),
453
- /* @__PURE__ */ jsxDEV2("nav", {
454
- className: "bg-muted flex gap-1 rounded-lg p-1",
455
- role: "tablist",
456
- children: tabs.map((tab) => /* @__PURE__ */ jsxDEV2(Button, {
457
- type: "button",
458
- role: "tab",
459
- "aria-selected": activeTab === tab.id,
460
- onClick: () => setActiveTab(tab.id),
461
- className: `flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-colors ${activeTab === tab.id ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
462
- children: [
463
- /* @__PURE__ */ jsxDEV2("span", {
464
- children: tab.icon
465
- }, undefined, false, undefined, this),
466
- tab.label
467
- ]
468
- }, tab.id, true, undefined, this))
469
- }, undefined, false, undefined, this),
470
- /* @__PURE__ */ jsxDEV2("div", {
471
- className: "min-h-[400px]",
472
- role: "tabpanel",
473
- children: [
474
- activeTab === "integrations" && /* @__PURE__ */ jsxDEV2("div", {
475
- className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3",
476
- children: [
477
- integrations.map((integration) => /* @__PURE__ */ jsxDEV2("div", {
478
- className: "border-border bg-card hover:bg-muted/50 cursor-pointer rounded-lg border p-4 transition-colors",
479
- children: [
480
- /* @__PURE__ */ jsxDEV2("div", {
481
- className: "mb-3 flex items-center gap-3",
482
- children: [
483
- /* @__PURE__ */ jsxDEV2("span", {
484
- className: "text-2xl",
485
- children: TYPE_ICONS[integration.type] ?? "\u2699\uFE0F"
486
- }, undefined, false, undefined, this),
487
- /* @__PURE__ */ jsxDEV2("div", {
488
- children: [
489
- /* @__PURE__ */ jsxDEV2("h3", {
490
- className: "font-medium",
491
- children: integration.name
492
- }, undefined, false, undefined, this),
493
- /* @__PURE__ */ jsxDEV2("p", {
494
- className: "text-muted-foreground text-sm",
495
- children: integration.type
496
- }, undefined, false, undefined, this)
497
- ]
498
- }, undefined, true, undefined, this)
499
- ]
500
- }, undefined, true, undefined, this),
501
- /* @__PURE__ */ jsxDEV2("div", {
502
- className: "flex items-center justify-between",
503
- children: [
504
- /* @__PURE__ */ jsxDEV2("span", {
505
- className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${STATUS_COLORS[integration.status] ?? ""}`,
506
- children: integration.status
507
- }, undefined, false, undefined, this),
508
- /* @__PURE__ */ jsxDEV2("span", {
509
- className: "text-muted-foreground text-xs",
510
- children: integration.createdAt.toLocaleDateString()
511
- }, undefined, false, undefined, this)
512
- ]
513
- }, undefined, true, undefined, this)
514
- ]
515
- }, integration.id, true, undefined, this)),
516
- integrations.length === 0 && /* @__PURE__ */ jsxDEV2("div", {
517
- className: "text-muted-foreground col-span-full flex h-64 items-center justify-center",
518
- children: "No integrations configured"
519
- }, undefined, false, undefined, this)
520
- ]
521
- }, undefined, true, undefined, this),
522
- activeTab === "connections" && /* @__PURE__ */ jsxDEV2("div", {
523
- className: "border-border rounded-lg border",
524
- children: /* @__PURE__ */ jsxDEV2("table", {
525
- className: "w-full",
526
- children: [
527
- /* @__PURE__ */ jsxDEV2("thead", {
528
- className: "border-border bg-muted/30 border-b",
529
- children: /* @__PURE__ */ jsxDEV2("tr", {
530
- children: [
531
- /* @__PURE__ */ jsxDEV2("th", {
532
- className: "px-4 py-3 text-left text-sm font-medium",
533
- children: "Connection"
534
- }, undefined, false, undefined, this),
535
- /* @__PURE__ */ jsxDEV2("th", {
536
- className: "px-4 py-3 text-left text-sm font-medium",
537
- children: "Status"
538
- }, undefined, false, undefined, this),
539
- /* @__PURE__ */ jsxDEV2("th", {
540
- className: "px-4 py-3 text-left text-sm font-medium",
541
- children: "Last Sync"
542
- }, undefined, false, undefined, this)
543
- ]
544
- }, undefined, true, undefined, this)
545
- }, undefined, false, undefined, this),
546
- /* @__PURE__ */ jsxDEV2("tbody", {
547
- className: "divide-border divide-y",
548
- children: [
549
- connections.map((conn) => /* @__PURE__ */ jsxDEV2("tr", {
550
- className: "hover:bg-muted/50",
551
- children: [
552
- /* @__PURE__ */ jsxDEV2("td", {
553
- className: "px-4 py-3",
554
- children: /* @__PURE__ */ jsxDEV2("div", {
555
- className: "font-medium",
556
- children: conn.name
557
- }, undefined, false, undefined, this)
558
- }, undefined, false, undefined, this),
559
- /* @__PURE__ */ jsxDEV2("td", {
560
- className: "px-4 py-3",
561
- children: /* @__PURE__ */ jsxDEV2("span", {
562
- className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${STATUS_COLORS[conn.status] ?? ""}`,
563
- children: conn.status
564
- }, undefined, false, undefined, this)
565
- }, undefined, false, undefined, this),
566
- /* @__PURE__ */ jsxDEV2("td", {
567
- className: "text-muted-foreground px-4 py-3 text-sm",
568
- children: conn.lastSyncAt?.toLocaleString() ?? "Never"
569
- }, undefined, false, undefined, this)
570
- ]
571
- }, conn.id, true, undefined, this)),
572
- connections.length === 0 && /* @__PURE__ */ jsxDEV2("tr", {
573
- children: /* @__PURE__ */ jsxDEV2("td", {
574
- colSpan: 3,
575
- className: "text-muted-foreground px-4 py-8 text-center",
576
- children: "No connections found"
577
- }, undefined, false, undefined, this)
578
- }, undefined, false, undefined, this)
579
- ]
580
- }, undefined, true, undefined, this)
581
- ]
582
- }, undefined, true, undefined, this)
583
- }, undefined, false, undefined, this),
584
- activeTab === "chat" && /* @__PURE__ */ jsxDEV2(IntegrationHubChat, {
585
- proxyUrl: "/api/chat",
586
- thinkingLevel: "thinking",
587
- suggestions: [
588
- "List my integrations",
589
- "Show sync status",
590
- "Add a connection"
591
- ],
592
- className: "min-h-[400px]"
593
- }, undefined, false, undefined, this),
594
- activeTab === "syncs" && /* @__PURE__ */ jsxDEV2("div", {
595
- className: "border-border rounded-lg border",
596
- children: /* @__PURE__ */ jsxDEV2("table", {
597
- className: "w-full",
598
- children: [
599
- /* @__PURE__ */ jsxDEV2("thead", {
600
- className: "border-border bg-muted/30 border-b",
601
- children: /* @__PURE__ */ jsxDEV2("tr", {
602
- children: [
603
- /* @__PURE__ */ jsxDEV2("th", {
604
- className: "px-4 py-3 text-left text-sm font-medium",
605
- children: "Sync Config"
606
- }, undefined, false, undefined, this),
607
- /* @__PURE__ */ jsxDEV2("th", {
608
- className: "px-4 py-3 text-left text-sm font-medium",
609
- children: "Frequency"
610
- }, undefined, false, undefined, this),
611
- /* @__PURE__ */ jsxDEV2("th", {
612
- className: "px-4 py-3 text-left text-sm font-medium",
613
- children: "Status"
614
- }, undefined, false, undefined, this),
615
- /* @__PURE__ */ jsxDEV2("th", {
616
- className: "px-4 py-3 text-left text-sm font-medium",
617
- children: "Records"
618
- }, undefined, false, undefined, this)
619
- ]
620
- }, undefined, true, undefined, this)
621
- }, undefined, false, undefined, this),
622
- /* @__PURE__ */ jsxDEV2("tbody", {
623
- className: "divide-border divide-y",
624
- children: [
625
- syncConfigs.map((sync) => /* @__PURE__ */ jsxDEV2("tr", {
626
- className: "hover:bg-muted/50",
627
- children: [
628
- /* @__PURE__ */ jsxDEV2("td", {
629
- className: "px-4 py-3",
630
- children: [
631
- /* @__PURE__ */ jsxDEV2("div", {
632
- className: "font-medium",
633
- children: sync.name
634
- }, undefined, false, undefined, this),
635
- /* @__PURE__ */ jsxDEV2("div", {
636
- className: "text-muted-foreground text-sm",
637
- children: [
638
- sync.sourceEntity,
639
- " \u2192 ",
640
- sync.targetEntity
641
- ]
642
- }, undefined, true, undefined, this)
643
- ]
644
- }, undefined, true, undefined, this),
645
- /* @__PURE__ */ jsxDEV2("td", {
646
- className: "px-4 py-3 text-sm",
647
- children: sync.frequency
648
- }, undefined, false, undefined, this),
649
- /* @__PURE__ */ jsxDEV2("td", {
650
- className: "px-4 py-3",
651
- children: /* @__PURE__ */ jsxDEV2("span", {
652
- className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${STATUS_COLORS[sync.status] ?? ""}`,
653
- children: sync.status
654
- }, undefined, false, undefined, this)
655
- }, undefined, false, undefined, this),
656
- /* @__PURE__ */ jsxDEV2("td", {
657
- className: "text-muted-foreground px-4 py-3 text-sm",
658
- children: sync.recordsSynced.toLocaleString()
659
- }, undefined, false, undefined, this)
660
- ]
661
- }, sync.id, true, undefined, this)),
662
- syncConfigs.length === 0 && /* @__PURE__ */ jsxDEV2("tr", {
663
- children: /* @__PURE__ */ jsxDEV2("td", {
664
- colSpan: 4,
665
- className: "text-muted-foreground px-4 py-8 text-center",
666
- children: "No sync configurations found"
667
- }, undefined, false, undefined, this)
668
- }, undefined, false, undefined, this)
669
- ]
670
- }, undefined, true, undefined, this)
671
- ]
672
- }, undefined, true, undefined, this)
673
- }, undefined, false, undefined, this)
674
- ]
675
- }, undefined, true, undefined, this)
676
- ]
677
- }, undefined, true, undefined, this);
678
- }
679
-
680
- // src/ui/hooks/index.ts
681
- "use client";
682
+ };
682
683
  export {
683
684
  useIntegrationData,
684
685
  syncConfigMarkdownRenderer,