@contractspec/example.integration-hub 3.8.22 → 3.9.1

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.
Files changed (38) hide show
  1. package/README.md +6 -1
  2. package/dist/docs/index.js +5 -2
  3. package/dist/docs/integration-hub.docblock.js +5 -2
  4. package/dist/handlers/index.js +5 -5
  5. package/dist/handlers/integration.handlers.js +5 -5
  6. package/dist/handlers/integration.handlers.preview.test.d.ts +1 -0
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.js +8 -8
  9. package/dist/node/docs/index.js +5 -2
  10. package/dist/node/docs/integration-hub.docblock.js +5 -2
  11. package/dist/node/handlers/index.js +5 -5
  12. package/dist/node/handlers/integration.handlers.js +5 -5
  13. package/dist/node/index.js +8 -8
  14. package/dist/node/setup/credential-setup.js +1 -0
  15. package/dist/node/setup/index.js +1 -0
  16. package/dist/node/ui/IntegrationDashboard.js +1 -1
  17. package/dist/node/ui/IntegrationHubCredentialSetupPreview.js +1 -0
  18. package/dist/node/ui/IntegrationHubCredentialSetupPreview.model.js +1 -0
  19. package/dist/node/ui/hooks/index.js +1 -1
  20. package/dist/node/ui/hooks/useIntegrationData.js +1 -1
  21. package/dist/node/ui/index.js +4 -4
  22. package/dist/setup/credential-setup.d.ts +158 -0
  23. package/dist/setup/credential-setup.js +2 -0
  24. package/dist/setup/index.d.ts +1 -0
  25. package/dist/setup/index.js +2 -0
  26. package/dist/ui/IntegrationDashboard.js +1 -1
  27. package/dist/ui/IntegrationDashboard.preview-runtime.test.d.ts +1 -0
  28. package/dist/ui/IntegrationHubCredentialSetupPreview.d.ts +6 -0
  29. package/dist/ui/IntegrationHubCredentialSetupPreview.js +2 -0
  30. package/dist/ui/IntegrationHubCredentialSetupPreview.model.d.ts +22 -0
  31. package/dist/ui/IntegrationHubCredentialSetupPreview.model.js +2 -0
  32. package/dist/ui/IntegrationHubCredentialSetupPreview.test.d.ts +1 -0
  33. package/dist/ui/hooks/index.js +1 -1
  34. package/dist/ui/hooks/useIntegrationData.d.ts +1 -1
  35. package/dist/ui/hooks/useIntegrationData.js +1 -1
  36. package/dist/ui/index.d.ts +1 -0
  37. package/dist/ui/index.js +4 -4
  38. package/package.json +59 -10
package/README.md CHANGED
@@ -15,6 +15,7 @@ Website: https://contractspec.io
15
15
  - Contract-backed visualizations for integration mix, connection health, and sync-state comparison.
16
16
  - Client-mode table capabilities including sorting, pagination, column visibility, pinning, resizing, and expanded operational details.
17
17
  - Event definitions and operation test-specs.
18
+ - Managed/BYOK credential setup metadata with monorepo-aware Next and Expo env aliases.
18
19
 
19
20
  ## Running Locally
20
21
 
@@ -37,6 +38,7 @@ Use `@contractspec/example.integration-hub` as a reference implementation, or im
37
38
  - `src/handlers/` contains handlers or demo adapters wired to contract surfaces.
38
39
  - `src/index.ts` is the root public barrel and package entrypoint.
39
40
  - `src/integration` is part of the package's public or composition surface.
41
+ - `src/setup` exposes BYOK credential manifests, secret-reference fixtures, and monorepo env aliases.
40
42
 
41
43
  ## Public Entry Points
42
44
 
@@ -50,7 +52,9 @@ Use `@contractspec/example.integration-hub` as a reference implementation, or im
50
52
  - Export `./docs/integration-hub.docblock` resolves through `./src/docs/integration-hub.docblock.ts`.
51
53
  - Export `./events` resolves through `./src/events.ts`.
52
54
  - Export `./example` resolves through `./src/example.ts`.
53
- - The package publishes 36 total export subpaths; keep docs aligned with `package.json`.
55
+ - Export `./setup` resolves through `./src/setup/index.ts`.
56
+ - Export `./setup/credential-setup` resolves through `./src/setup/credential-setup.ts`.
57
+ - The package publishes 46 total export subpaths; keep docs aligned with `package.json`.
54
58
 
55
59
  ## Local Commands
56
60
 
@@ -77,6 +81,7 @@ Use `@contractspec/example.integration-hub` as a reference implementation, or im
77
81
  - Resolve lint, build, and type errors across nine packages.
78
82
  - Add Composio universal fallback, fix provider-ranking types, and expand package exports.
79
83
  - Add first-class transport, auth, versioning, and BYOK support across all integrations.
84
+ - Add Integration Hub BYOK credential setup metadata and Next/Expo alias previews.
80
85
 
81
86
  ## Notes
82
87
 
@@ -16,7 +16,7 @@ import{registerDocBlocks as m}from"@contractspec/lib.contracts-spec/docs";var f=
16
16
 
17
17
  ## UI / Presentations
18
18
 
19
- - Dashboard, integration list, connection detail, sync config editor, and shared ContractSpec tables for connections/sync configs.
19
+ - Dashboard, integration list, connection detail, sync config editor, BYOK/env setup preview, and shared ContractSpec tables for connections/sync configs.
20
20
  - Templates registered as \`integration-hub\` in Template Registry.
21
21
 
22
22
  ## Notes
@@ -24,6 +24,7 @@ import{registerDocBlocks as m}from"@contractspec/lib.contracts-spec/docs";var f=
24
24
  - Providers remain agnostic; keep mappings declarative for safe regeneration.
25
25
  - Seed data includes voice integrations for \`ai-voice.gradium\` and \`ai-voice.fal\`.
26
26
  - Feature flags can gate specific providers; metering can track sync volume.
27
+ - \`src/setup/credential-setup.ts\` demonstrates managed/BYOK credential manifests, secret references, and app-specific \`NEXT_PUBLIC_*\` / \`EXPO_PUBLIC_*\` aliases.
27
28
  - The dashboard tables demonstrate client-mode sorting, pagination, visibility, pinning, resizing, and row expansion on the shared table stack.
28
29
  `},{id:"docs.examples.integration-hub.goal",title:"Integration Hub \u2014 Goal",summary:"Why this integration hub exists and what success looks like.",kind:"goal",visibility:"public",route:"/docs/examples/integration-hub/goal",tags:["integrations","goal"],body:`## Why it matters
29
30
  - Gives a regenerable, provider-agnostic integration hub with explicit mappings.
@@ -38,7 +39,8 @@ import{registerDocBlocks as m}from"@contractspec/lib.contracts-spec/docs";var f=
38
39
  - Sync events and logs provide auditability; payloads are stored and PII-scoped.`},{id:"docs.examples.integration-hub.usage",title:"Integration Hub \u2014 Usage",summary:"How to configure connectors, mappings, and scheduled syncs.",kind:"usage",visibility:"public",route:"/docs/examples/integration-hub/usage",tags:["integrations","usage"],body:`## Setup
39
40
  1) Seed integrations/connections (if available) or create connector definitions.
40
41
  2) Configure sync jobs with Jobs module; store payload archives via Files.
41
- 3) Use \`src/run-mcp.ts\` to validate MCP connectivity for provider adapters.
42
+ 3) Use \`src/setup/credential-setup.ts\` to map managed/BYOK fields to per-app env aliases.
43
+ 4) Use \`src/run-mcp.ts\` to validate MCP connectivity for provider adapters.
42
44
 
43
45
  ## Extend & regenerate
44
46
  1) Add mapping fields or provider configs in the spec; include validation and PII paths.
@@ -56,6 +58,7 @@ import{registerDocBlocks as m}from"@contractspec/lib.contracts-spec/docs";var f=
56
58
  ## PII & Payloads
57
59
  - Treat payload archives as potentially sensitive; mark policy.pii paths.
58
60
  - For MCP/web, avoid exposing raw credentials/tokens; store via provider adapters only.
61
+ - Secret fields must not be materialized through public aliases such as \`NEXT_PUBLIC_*\` or \`EXPO_PUBLIC_*\`.
59
62
  - Keep MCP endpoint URLs, headers, and tokens in provider connection config, never in mappings.
60
63
 
61
64
  ## Verification
@@ -16,7 +16,7 @@ import{registerDocBlocks as f}from"@contractspec/lib.contracts-spec/docs";var h=
16
16
 
17
17
  ## UI / Presentations
18
18
 
19
- - Dashboard, integration list, connection detail, sync config editor, and shared ContractSpec tables for connections/sync configs.
19
+ - Dashboard, integration list, connection detail, sync config editor, BYOK/env setup preview, and shared ContractSpec tables for connections/sync configs.
20
20
  - Templates registered as \`integration-hub\` in Template Registry.
21
21
 
22
22
  ## Notes
@@ -24,6 +24,7 @@ import{registerDocBlocks as f}from"@contractspec/lib.contracts-spec/docs";var h=
24
24
  - Providers remain agnostic; keep mappings declarative for safe regeneration.
25
25
  - Seed data includes voice integrations for \`ai-voice.gradium\` and \`ai-voice.fal\`.
26
26
  - Feature flags can gate specific providers; metering can track sync volume.
27
+ - \`src/setup/credential-setup.ts\` demonstrates managed/BYOK credential manifests, secret references, and app-specific \`NEXT_PUBLIC_*\` / \`EXPO_PUBLIC_*\` aliases.
27
28
  - The dashboard tables demonstrate client-mode sorting, pagination, visibility, pinning, resizing, and row expansion on the shared table stack.
28
29
  `},{id:"docs.examples.integration-hub.goal",title:"Integration Hub \u2014 Goal",summary:"Why this integration hub exists and what success looks like.",kind:"goal",visibility:"public",route:"/docs/examples/integration-hub/goal",tags:["integrations","goal"],body:`## Why it matters
29
30
  - Gives a regenerable, provider-agnostic integration hub with explicit mappings.
@@ -38,7 +39,8 @@ import{registerDocBlocks as f}from"@contractspec/lib.contracts-spec/docs";var h=
38
39
  - Sync events and logs provide auditability; payloads are stored and PII-scoped.`},{id:"docs.examples.integration-hub.usage",title:"Integration Hub \u2014 Usage",summary:"How to configure connectors, mappings, and scheduled syncs.",kind:"usage",visibility:"public",route:"/docs/examples/integration-hub/usage",tags:["integrations","usage"],body:`## Setup
39
40
  1) Seed integrations/connections (if available) or create connector definitions.
40
41
  2) Configure sync jobs with Jobs module; store payload archives via Files.
41
- 3) Use \`src/run-mcp.ts\` to validate MCP connectivity for provider adapters.
42
+ 3) Use \`src/setup/credential-setup.ts\` to map managed/BYOK fields to per-app env aliases.
43
+ 4) Use \`src/run-mcp.ts\` to validate MCP connectivity for provider adapters.
42
44
 
43
45
  ## Extend & regenerate
44
46
  1) Add mapping fields or provider configs in the spec; include validation and PII paths.
@@ -56,6 +58,7 @@ import{registerDocBlocks as f}from"@contractspec/lib.contracts-spec/docs";var h=
56
58
  ## PII & Payloads
57
59
  - Treat payload archives as potentially sensitive; mark policy.pii paths.
58
60
  - For MCP/web, avoid exposing raw credentials/tokens; store via provider adapters only.
61
+ - Secret fields must not be materialized through public aliases such as \`NEXT_PUBLIC_*\` or \`EXPO_PUBLIC_*\`.
59
62
  - Keep MCP endpoint URLs, headers, and tokens in provider connection config, never in mappings.
60
63
 
61
64
  ## Verification
@@ -1,6 +1,6 @@
1
1
  // @bun
2
- import{web as S}from"@contractspec/lib.runtime-sandbox";var{generateId:R}=S;function Y(q){return{id:q.id,projectId:q.projectId,organizationId:q.organizationId,name:q.name,description:q.description??void 0,type:q.type,status:q.status,iconUrl:q.iconUrl??void 0,createdAt:new Date(q.createdAt),updatedAt:new Date(q.updatedAt)}}function U(q){return{id:q.id,integrationId:q.integrationId,name:q.name,status:q.status,credentials:q.credentials?JSON.parse(q.credentials):void 0,config:q.config?JSON.parse(q.config):void 0,lastSyncAt:q.lastSyncAt?new Date(q.lastSyncAt):void 0,errorMessage:q.errorMessage??void 0,createdAt:new Date(q.createdAt),updatedAt:new Date(q.updatedAt)}}function W(q){return{id:q.id,connectionId:q.connectionId,name:q.name,sourceEntity:q.sourceEntity,targetEntity:q.targetEntity,frequency:q.frequency,status:q.status,lastRunAt:q.lastRunAt?new Date(q.lastRunAt):void 0,lastRunStatus:q.lastRunStatus??void 0,recordsSynced:q.recordsSynced,createdAt:new Date(q.createdAt),updatedAt:new Date(q.updatedAt)}}function Z(q){return{id:q.id,syncConfigId:q.syncConfigId,sourceField:q.sourceField,targetField:q.targetField,transformType:q.transformType??void 0,transformConfig:q.transformConfig?JSON.parse(q.transformConfig):void 0,createdAt:new Date(q.createdAt)}}function y(q){async function _(z){let{projectId:D,type:E,status:G,search:H,limit:J=20,offset:L=0}=z,Q="WHERE projectId = ?",N=[D];if(E&&E!=="all")Q+=" AND type = ?",N.push(E);if(G&&G!=="all")Q+=" AND status = ?",N.push(G);if(H)Q+=" AND name LIKE ?",N.push(`%${H}%`);let k=(await q.query(`SELECT COUNT(*) as count FROM integration ${Q}`,N)).rows[0]?.count??0;return{integrations:(await q.query(`SELECT * FROM integration ${Q} ORDER BY name LIMIT ? OFFSET ?`,[...N,J,L])).rows.map(Y),total:k}}async function $(z,D){let E=R("integ"),G=new Date().toISOString();await q.execute(`INSERT INTO integration (id, projectId, organizationId, name, description, type, status, iconUrl, createdAt, updatedAt)
3
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[E,D.projectId,D.organizationId,z.name,z.description??null,z.type,"INACTIVE",z.iconUrl??null,G,G]);let H=(await q.query("SELECT * FROM integration WHERE id = ?",[E])).rows;return Y(H[0])}async function j(z){let{integrationId:D,status:E,limit:G=20,offset:H=0}=z,J="WHERE 1=1",L=[];if(D)J+=" AND integrationId = ?",L.push(D);if(E&&E!=="all")J+=" AND status = ?",L.push(E);let N=(await q.query(`SELECT COUNT(*) as count FROM integration_connection ${J}`,L)).rows[0]?.count??0;return{connections:(await q.query(`SELECT * FROM integration_connection ${J} ORDER BY updatedAt DESC LIMIT ? OFFSET ?`,[...L,G,H])).rows.map(U),total:N}}async function A(z){let D=R("conn"),E=new Date().toISOString();await q.execute(`INSERT INTO integration_connection (id, integrationId, name, status, credentials, config, createdAt, updatedAt)
4
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,[D,z.integrationId,z.name,"PENDING",z.credentials?JSON.stringify(z.credentials):null,z.config?JSON.stringify(z.config):null,E,E]),await q.execute("UPDATE integration_connection SET status = 'CONNECTED', updatedAt = ? WHERE id = ?",[E,D]),await q.execute("UPDATE integration SET status = 'ACTIVE', updatedAt = ? WHERE id = ?",[E,z.integrationId]);let G=(await q.query("SELECT * FROM integration_connection WHERE id = ?",[D])).rows;return U(G[0])}async function B(z){let D=new Date().toISOString();await q.execute("UPDATE integration_connection SET status = 'DISCONNECTED', updatedAt = ? WHERE id = ?",[D,z]);let E=(await q.query("SELECT * FROM integration_connection WHERE id = ?",[z])).rows;return U(E[0])}async function K(z){let{connectionId:D,status:E,limit:G=20,offset:H=0}=z,J="WHERE 1=1",L=[];if(D)J+=" AND connectionId = ?",L.push(D);if(E&&E!=="all")J+=" AND status = ?",L.push(E);let N=(await q.query(`SELECT COUNT(*) as count FROM integration_sync_config ${J}`,L)).rows[0]?.count??0;return{configs:(await q.query(`SELECT * FROM integration_sync_config ${J} ORDER BY updatedAt DESC LIMIT ? OFFSET ?`,[...L,G,H])).rows.map(W),total:N}}async function P(z){let D=R("sync"),E=new Date().toISOString();await q.execute(`INSERT INTO integration_sync_config (id, connectionId, name, sourceEntity, targetEntity, frequency, status, recordsSynced, createdAt, updatedAt)
5
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[D,z.connectionId,z.name,z.sourceEntity,z.targetEntity,z.frequency??"DAILY","ACTIVE",0,E,E]);let G=(await q.query("SELECT * FROM integration_sync_config WHERE id = ?",[D])).rows;return W(G[0])}async function O(z){let D=new Date().toISOString(),E=[];await q.execute("DELETE FROM integration_field_mapping WHERE syncConfigId = ?",[z.syncConfigId]);for(let G of z.mappings){let H=R("fmap");await q.execute(`INSERT INTO integration_field_mapping (id, syncConfigId, sourceField, targetField, transformType, transformConfig, createdAt)
6
- VALUES (?, ?, ?, ?, ?, ?, ?)`,[H,z.syncConfigId,G.sourceField,G.targetField,G.transformType??null,G.transformConfig?JSON.stringify(G.transformConfig):null,D]);let J=(await q.query("SELECT * FROM integration_field_mapping WHERE id = ?",[H])).rows;E.push(Z(J[0]))}return E}async function v(z){return(await q.query("SELECT * FROM integration_field_mapping WHERE syncConfigId = ?",[z])).rows.map(Z)}async function M(z){let D=new Date().toISOString(),E=Math.floor(Math.random()*1000)+50;await q.execute("UPDATE integration_sync_config SET lastRunAt = ?, lastRunStatus = 'SUCCESS', recordsSynced = recordsSynced + ?, updatedAt = ? WHERE id = ?",[D,E,D,z]);let G=(await q.query("SELECT * FROM integration_sync_config WHERE id = ?",[z])).rows;if(G[0])await q.execute("UPDATE integration_connection SET lastSyncAt = ?, updatedAt = ? WHERE id = ?",[D,D,G[0].connectionId]);let H=(await q.query("SELECT * FROM integration_sync_config WHERE id = ?",[z])).rows;return W(H[0])}async function V(z){let D=(await q.query("SELECT * FROM integration_connection WHERE id = ?",[z.connectionId])).rows;if(!D[0])return{valid:!1,provider:"unknown",keyPrefix:"",error:`Connection ${z.connectionId} not found`};let E=z.providerKey.slice(0,8),G=z.providerKey.length>=16;return{valid:G,provider:D[0].name,keyPrefix:`${E}...`,expiresAt:G?new Date(Date.now()+7776000000).toISOString():void 0,error:G?void 0:"Key must be at least 16 characters"}}async function F(z){let D=new Date().toISOString();return await q.execute("UPDATE integration_connection SET updatedAt = ? WHERE id = ?",[D,z.connectionId]),{refreshed:!0,expiresAt:new Date(Date.now()+3600000).toISOString(),tokenType:"Bearer",scopes:["read","write","sync"]}}async function x(z){return{integrationId:z.integrationId,transports:[{transport:"rest",supported:!0,defaultVersion:"v2"},{transport:"mcp",supported:!0,defaultVersion:"v1"},{transport:"webhook",supported:!0},{transport:"sdk",supported:!1}]}}return{listIntegrations:_,createIntegration:$,listConnections:j,connectService:A,disconnectService:B,listSyncConfigs:K,configureSync:P,mapFields:O,getFieldMappings:v,runSync:M,validateByokKey:V,refreshOAuth2Token:F,getTransportOptions:x}}export{y as createIntegrationHandlers};
2
+ import{web as S}from"@contractspec/lib.runtime-sandbox";var{generateId:R}=S;function Y(q){return{id:q.id,projectId:q.projectId,organizationId:q.organizationId,name:q.name,description:q.description??void 0,type:q.type,status:q.status,iconUrl:q.iconUrl??void 0,createdAt:new Date(q.createdAt),updatedAt:new Date(q.updatedAt)}}function U(q){return{id:q.id,integrationId:q.integrationId,name:q.name,status:q.status,credentials:q.credentials?JSON.parse(q.credentials):void 0,config:q.config?JSON.parse(q.config):void 0,lastSyncAt:q.lastSyncAt?new Date(q.lastSyncAt):void 0,errorMessage:q.errorMessage??void 0,createdAt:new Date(q.createdAt),updatedAt:new Date(q.updatedAt)}}function W(q){return{id:q.id,connectionId:q.connectionId,name:q.name,sourceEntity:q.sourceEntity,targetEntity:q.targetEntity,frequency:q.frequency,status:q.status,lastRunAt:q.lastRunAt?new Date(q.lastRunAt):void 0,lastRunStatus:q.lastRunStatus??void 0,recordsSynced:q.recordsSynced,createdAt:new Date(q.createdAt),updatedAt:new Date(q.updatedAt)}}function Z(q){return{id:q.id,syncConfigId:q.syncConfigId,sourceField:q.sourceField,targetField:q.targetField,transformType:q.transformType??void 0,transformConfig:q.transformConfig?JSON.parse(q.transformConfig):void 0,createdAt:new Date(q.createdAt)}}function y(q){async function _(z){let{projectId:D,type:E,status:G,search:L,limit:N=20,offset:H=0}=z,Q='WHERE "projectId" = $1',J=[D];if(E&&E!=="all")Q+=` AND type = $${J.length+1}`,J.push(E);if(G&&G!=="all")Q+=` AND status = $${J.length+1}`,J.push(G);if(L)Q+=` AND name LIKE $${J.length+1}`,J.push(`%${L}%`);let k=(await q.query(`SELECT COUNT(*) as count FROM integration ${Q}`,J)).rows[0]?.count??0;return{integrations:(await q.query(`SELECT * FROM integration ${Q} ORDER BY name LIMIT $${J.length+1} OFFSET $${J.length+2}`,[...J,N,H])).rows.map(Y),total:k}}async function $(z,D){let E=R("integ"),G=new Date().toISOString();await q.execute(`INSERT INTO integration (id, "projectId", "organizationId", name, description, type, status, "iconUrl", "createdAt", "updatedAt")
3
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`,[E,D.projectId,D.organizationId,z.name,z.description??null,z.type,"INACTIVE",z.iconUrl??null,G,G]);let L=(await q.query("SELECT * FROM integration WHERE id = $1",[E])).rows;return Y(L[0])}async function j(z){let{integrationId:D,status:E,limit:G=20,offset:L=0}=z,N="WHERE 1=1",H=[];if(D)N+=` AND "integrationId" = $${H.length+1}`,H.push(D);if(E&&E!=="all")N+=` AND status = $${H.length+1}`,H.push(E);let J=(await q.query(`SELECT COUNT(*) as count FROM integration_connection ${N}`,H)).rows[0]?.count??0;return{connections:(await q.query(`SELECT * FROM integration_connection ${N} ORDER BY "updatedAt" DESC LIMIT $${H.length+1} OFFSET $${H.length+2}`,[...H,G,L])).rows.map(U),total:J}}async function A(z){let D=R("conn"),E=new Date().toISOString();await q.execute(`INSERT INTO integration_connection (id, "integrationId", name, status, credentials, config, "createdAt", "updatedAt")
4
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,[D,z.integrationId,z.name,"PENDING",z.credentials?JSON.stringify(z.credentials):null,z.config?JSON.stringify(z.config):null,E,E]),await q.execute(`UPDATE integration_connection SET status = 'CONNECTED', "updatedAt" = $1 WHERE id = $2`,[E,D]),await q.execute(`UPDATE integration SET status = 'ACTIVE', "updatedAt" = $1 WHERE id = $2`,[E,z.integrationId]);let G=(await q.query("SELECT * FROM integration_connection WHERE id = $1",[D])).rows;return U(G[0])}async function B(z){let D=new Date().toISOString();await q.execute(`UPDATE integration_connection SET status = 'DISCONNECTED', "updatedAt" = $1 WHERE id = $2`,[D,z]);let E=(await q.query("SELECT * FROM integration_connection WHERE id = $1",[z])).rows;return U(E[0])}async function K(z){let{connectionId:D,status:E,limit:G=20,offset:L=0}=z,N="WHERE 1=1",H=[];if(D)N+=` AND "connectionId" = $${H.length+1}`,H.push(D);if(E&&E!=="all")N+=` AND status = $${H.length+1}`,H.push(E);let J=(await q.query(`SELECT COUNT(*) as count FROM integration_sync_config ${N}`,H)).rows[0]?.count??0;return{configs:(await q.query(`SELECT * FROM integration_sync_config ${N} ORDER BY "updatedAt" DESC LIMIT $${H.length+1} OFFSET $${H.length+2}`,[...H,G,L])).rows.map(W),total:J}}async function P(z){let D=R("sync"),E=new Date().toISOString();await q.execute(`INSERT INTO integration_sync_config (id, "connectionId", name, "sourceEntity", "targetEntity", frequency, status, "recordsSynced", "createdAt", "updatedAt")
5
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`,[D,z.connectionId,z.name,z.sourceEntity,z.targetEntity,z.frequency??"DAILY","ACTIVE",0,E,E]);let G=(await q.query("SELECT * FROM integration_sync_config WHERE id = $1",[D])).rows;return W(G[0])}async function O(z){let D=new Date().toISOString(),E=[];await q.execute('DELETE FROM integration_field_mapping WHERE "syncConfigId" = $1',[z.syncConfigId]);for(let G of z.mappings){let L=R("fmap");await q.execute(`INSERT INTO integration_field_mapping (id, "syncConfigId", "sourceField", "targetField", "transformType", "transformConfig", "createdAt")
6
+ VALUES ($1, $2, $3, $4, $5, $6, $7)`,[L,z.syncConfigId,G.sourceField,G.targetField,G.transformType??null,G.transformConfig?JSON.stringify(G.transformConfig):null,D]);let N=(await q.query("SELECT * FROM integration_field_mapping WHERE id = $1",[L])).rows;E.push(Z(N[0]))}return E}async function v(z){return(await q.query('SELECT * FROM integration_field_mapping WHERE "syncConfigId" = $1',[z])).rows.map(Z)}async function M(z){let D=new Date().toISOString(),E=Math.floor(Math.random()*1000)+50;await q.execute(`UPDATE integration_sync_config SET "lastRunAt" = $1, "lastRunStatus" = 'SUCCESS', "recordsSynced" = "recordsSynced" + $2, "updatedAt" = $3 WHERE id = $4`,[D,E,D,z]);let G=(await q.query("SELECT * FROM integration_sync_config WHERE id = $1",[z])).rows;if(G[0])await q.execute('UPDATE integration_connection SET "lastSyncAt" = $1, "updatedAt" = $2 WHERE id = $3',[D,D,G[0].connectionId]);let L=(await q.query("SELECT * FROM integration_sync_config WHERE id = $1",[z])).rows;return W(L[0])}async function V(z){let D=(await q.query("SELECT * FROM integration_connection WHERE id = $1",[z.connectionId])).rows;if(!D[0])return{valid:!1,provider:"unknown",keyPrefix:"",error:`Connection ${z.connectionId} not found`};let E=z.providerKey.slice(0,8),G=z.providerKey.length>=16;return{valid:G,provider:D[0].name,keyPrefix:`${E}...`,expiresAt:G?new Date(Date.now()+7776000000).toISOString():void 0,error:G?void 0:"Key must be at least 16 characters"}}async function F(z){let D=new Date().toISOString();return await q.execute('UPDATE integration_connection SET "updatedAt" = $1 WHERE id = $2',[D,z.connectionId]),{refreshed:!0,expiresAt:new Date(Date.now()+3600000).toISOString(),tokenType:"Bearer",scopes:["read","write","sync"]}}async function x(z){return{integrationId:z.integrationId,transports:[{transport:"rest",supported:!0,defaultVersion:"v2"},{transport:"mcp",supported:!0,defaultVersion:"v1"},{transport:"webhook",supported:!0},{transport:"sdk",supported:!1}]}}return{listIntegrations:_,createIntegration:$,listConnections:j,connectService:A,disconnectService:B,listSyncConfigs:K,configureSync:P,mapFields:O,getFieldMappings:v,runSync:M,validateByokKey:V,refreshOAuth2Token:F,getTransportOptions:x}}export{y as createIntegrationHandlers};
@@ -1,6 +1,6 @@
1
1
  // @bun
2
- import{web as S}from"@contractspec/lib.runtime-sandbox";var{generateId:R}=S;function Y(q){return{id:q.id,projectId:q.projectId,organizationId:q.organizationId,name:q.name,description:q.description??void 0,type:q.type,status:q.status,iconUrl:q.iconUrl??void 0,createdAt:new Date(q.createdAt),updatedAt:new Date(q.updatedAt)}}function U(q){return{id:q.id,integrationId:q.integrationId,name:q.name,status:q.status,credentials:q.credentials?JSON.parse(q.credentials):void 0,config:q.config?JSON.parse(q.config):void 0,lastSyncAt:q.lastSyncAt?new Date(q.lastSyncAt):void 0,errorMessage:q.errorMessage??void 0,createdAt:new Date(q.createdAt),updatedAt:new Date(q.updatedAt)}}function W(q){return{id:q.id,connectionId:q.connectionId,name:q.name,sourceEntity:q.sourceEntity,targetEntity:q.targetEntity,frequency:q.frequency,status:q.status,lastRunAt:q.lastRunAt?new Date(q.lastRunAt):void 0,lastRunStatus:q.lastRunStatus??void 0,recordsSynced:q.recordsSynced,createdAt:new Date(q.createdAt),updatedAt:new Date(q.updatedAt)}}function Z(q){return{id:q.id,syncConfigId:q.syncConfigId,sourceField:q.sourceField,targetField:q.targetField,transformType:q.transformType??void 0,transformConfig:q.transformConfig?JSON.parse(q.transformConfig):void 0,createdAt:new Date(q.createdAt)}}function y(q){async function _(z){let{projectId:D,type:E,status:G,search:H,limit:J=20,offset:L=0}=z,Q="WHERE projectId = ?",N=[D];if(E&&E!=="all")Q+=" AND type = ?",N.push(E);if(G&&G!=="all")Q+=" AND status = ?",N.push(G);if(H)Q+=" AND name LIKE ?",N.push(`%${H}%`);let x=(await q.query(`SELECT COUNT(*) as count FROM integration ${Q}`,N)).rows[0]?.count??0;return{integrations:(await q.query(`SELECT * FROM integration ${Q} ORDER BY name LIMIT ? OFFSET ?`,[...N,J,L])).rows.map(Y),total:x}}async function $(z,D){let E=R("integ"),G=new Date().toISOString();await q.execute(`INSERT INTO integration (id, projectId, organizationId, name, description, type, status, iconUrl, createdAt, updatedAt)
3
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[E,D.projectId,D.organizationId,z.name,z.description??null,z.type,"INACTIVE",z.iconUrl??null,G,G]);let H=(await q.query("SELECT * FROM integration WHERE id = ?",[E])).rows;return Y(H[0])}async function j(z){let{integrationId:D,status:E,limit:G=20,offset:H=0}=z,J="WHERE 1=1",L=[];if(D)J+=" AND integrationId = ?",L.push(D);if(E&&E!=="all")J+=" AND status = ?",L.push(E);let N=(await q.query(`SELECT COUNT(*) as count FROM integration_connection ${J}`,L)).rows[0]?.count??0;return{connections:(await q.query(`SELECT * FROM integration_connection ${J} ORDER BY updatedAt DESC LIMIT ? OFFSET ?`,[...L,G,H])).rows.map(U),total:N}}async function A(z){let D=R("conn"),E=new Date().toISOString();await q.execute(`INSERT INTO integration_connection (id, integrationId, name, status, credentials, config, createdAt, updatedAt)
4
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,[D,z.integrationId,z.name,"PENDING",z.credentials?JSON.stringify(z.credentials):null,z.config?JSON.stringify(z.config):null,E,E]),await q.execute("UPDATE integration_connection SET status = 'CONNECTED', updatedAt = ? WHERE id = ?",[E,D]),await q.execute("UPDATE integration SET status = 'ACTIVE', updatedAt = ? WHERE id = ?",[E,z.integrationId]);let G=(await q.query("SELECT * FROM integration_connection WHERE id = ?",[D])).rows;return U(G[0])}async function B(z){let D=new Date().toISOString();await q.execute("UPDATE integration_connection SET status = 'DISCONNECTED', updatedAt = ? WHERE id = ?",[D,z]);let E=(await q.query("SELECT * FROM integration_connection WHERE id = ?",[z])).rows;return U(E[0])}async function K(z){let{connectionId:D,status:E,limit:G=20,offset:H=0}=z,J="WHERE 1=1",L=[];if(D)J+=" AND connectionId = ?",L.push(D);if(E&&E!=="all")J+=" AND status = ?",L.push(E);let N=(await q.query(`SELECT COUNT(*) as count FROM integration_sync_config ${J}`,L)).rows[0]?.count??0;return{configs:(await q.query(`SELECT * FROM integration_sync_config ${J} ORDER BY updatedAt DESC LIMIT ? OFFSET ?`,[...L,G,H])).rows.map(W),total:N}}async function P(z){let D=R("sync"),E=new Date().toISOString();await q.execute(`INSERT INTO integration_sync_config (id, connectionId, name, sourceEntity, targetEntity, frequency, status, recordsSynced, createdAt, updatedAt)
5
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[D,z.connectionId,z.name,z.sourceEntity,z.targetEntity,z.frequency??"DAILY","ACTIVE",0,E,E]);let G=(await q.query("SELECT * FROM integration_sync_config WHERE id = ?",[D])).rows;return W(G[0])}async function O(z){let D=new Date().toISOString(),E=[];await q.execute("DELETE FROM integration_field_mapping WHERE syncConfigId = ?",[z.syncConfigId]);for(let G of z.mappings){let H=R("fmap");await q.execute(`INSERT INTO integration_field_mapping (id, syncConfigId, sourceField, targetField, transformType, transformConfig, createdAt)
6
- VALUES (?, ?, ?, ?, ?, ?, ?)`,[H,z.syncConfigId,G.sourceField,G.targetField,G.transformType??null,G.transformConfig?JSON.stringify(G.transformConfig):null,D]);let J=(await q.query("SELECT * FROM integration_field_mapping WHERE id = ?",[H])).rows;E.push(Z(J[0]))}return E}async function v(z){return(await q.query("SELECT * FROM integration_field_mapping WHERE syncConfigId = ?",[z])).rows.map(Z)}async function M(z){let D=new Date().toISOString(),E=Math.floor(Math.random()*1000)+50;await q.execute("UPDATE integration_sync_config SET lastRunAt = ?, lastRunStatus = 'SUCCESS', recordsSynced = recordsSynced + ?, updatedAt = ? WHERE id = ?",[D,E,D,z]);let G=(await q.query("SELECT * FROM integration_sync_config WHERE id = ?",[z])).rows;if(G[0])await q.execute("UPDATE integration_connection SET lastSyncAt = ?, updatedAt = ? WHERE id = ?",[D,D,G[0].connectionId]);let H=(await q.query("SELECT * FROM integration_sync_config WHERE id = ?",[z])).rows;return W(H[0])}async function V(z){let D=(await q.query("SELECT * FROM integration_connection WHERE id = ?",[z.connectionId])).rows;if(!D[0])return{valid:!1,provider:"unknown",keyPrefix:"",error:`Connection ${z.connectionId} not found`};let E=z.providerKey.slice(0,8),G=z.providerKey.length>=16;return{valid:G,provider:D[0].name,keyPrefix:`${E}...`,expiresAt:G?new Date(Date.now()+7776000000).toISOString():void 0,error:G?void 0:"Key must be at least 16 characters"}}async function F(z){let D=new Date().toISOString();return await q.execute("UPDATE integration_connection SET updatedAt = ? WHERE id = ?",[D,z.connectionId]),{refreshed:!0,expiresAt:new Date(Date.now()+3600000).toISOString(),tokenType:"Bearer",scopes:["read","write","sync"]}}async function k(z){return{integrationId:z.integrationId,transports:[{transport:"rest",supported:!0,defaultVersion:"v2"},{transport:"mcp",supported:!0,defaultVersion:"v1"},{transport:"webhook",supported:!0},{transport:"sdk",supported:!1}]}}return{listIntegrations:_,createIntegration:$,listConnections:j,connectService:A,disconnectService:B,listSyncConfigs:K,configureSync:P,mapFields:O,getFieldMappings:v,runSync:M,validateByokKey:V,refreshOAuth2Token:F,getTransportOptions:k}}export{y as createIntegrationHandlers};
2
+ import{web as S}from"@contractspec/lib.runtime-sandbox";var{generateId:R}=S;function Y(q){return{id:q.id,projectId:q.projectId,organizationId:q.organizationId,name:q.name,description:q.description??void 0,type:q.type,status:q.status,iconUrl:q.iconUrl??void 0,createdAt:new Date(q.createdAt),updatedAt:new Date(q.updatedAt)}}function U(q){return{id:q.id,integrationId:q.integrationId,name:q.name,status:q.status,credentials:q.credentials?JSON.parse(q.credentials):void 0,config:q.config?JSON.parse(q.config):void 0,lastSyncAt:q.lastSyncAt?new Date(q.lastSyncAt):void 0,errorMessage:q.errorMessage??void 0,createdAt:new Date(q.createdAt),updatedAt:new Date(q.updatedAt)}}function W(q){return{id:q.id,connectionId:q.connectionId,name:q.name,sourceEntity:q.sourceEntity,targetEntity:q.targetEntity,frequency:q.frequency,status:q.status,lastRunAt:q.lastRunAt?new Date(q.lastRunAt):void 0,lastRunStatus:q.lastRunStatus??void 0,recordsSynced:q.recordsSynced,createdAt:new Date(q.createdAt),updatedAt:new Date(q.updatedAt)}}function Z(q){return{id:q.id,syncConfigId:q.syncConfigId,sourceField:q.sourceField,targetField:q.targetField,transformType:q.transformType??void 0,transformConfig:q.transformConfig?JSON.parse(q.transformConfig):void 0,createdAt:new Date(q.createdAt)}}function y(q){async function _(z){let{projectId:D,type:E,status:G,search:L,limit:N=20,offset:H=0}=z,Q='WHERE "projectId" = $1',J=[D];if(E&&E!=="all")Q+=` AND type = $${J.length+1}`,J.push(E);if(G&&G!=="all")Q+=` AND status = $${J.length+1}`,J.push(G);if(L)Q+=` AND name LIKE $${J.length+1}`,J.push(`%${L}%`);let x=(await q.query(`SELECT COUNT(*) as count FROM integration ${Q}`,J)).rows[0]?.count??0;return{integrations:(await q.query(`SELECT * FROM integration ${Q} ORDER BY name LIMIT $${J.length+1} OFFSET $${J.length+2}`,[...J,N,H])).rows.map(Y),total:x}}async function $(z,D){let E=R("integ"),G=new Date().toISOString();await q.execute(`INSERT INTO integration (id, "projectId", "organizationId", name, description, type, status, "iconUrl", "createdAt", "updatedAt")
3
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`,[E,D.projectId,D.organizationId,z.name,z.description??null,z.type,"INACTIVE",z.iconUrl??null,G,G]);let L=(await q.query("SELECT * FROM integration WHERE id = $1",[E])).rows;return Y(L[0])}async function j(z){let{integrationId:D,status:E,limit:G=20,offset:L=0}=z,N="WHERE 1=1",H=[];if(D)N+=` AND "integrationId" = $${H.length+1}`,H.push(D);if(E&&E!=="all")N+=` AND status = $${H.length+1}`,H.push(E);let J=(await q.query(`SELECT COUNT(*) as count FROM integration_connection ${N}`,H)).rows[0]?.count??0;return{connections:(await q.query(`SELECT * FROM integration_connection ${N} ORDER BY "updatedAt" DESC LIMIT $${H.length+1} OFFSET $${H.length+2}`,[...H,G,L])).rows.map(U),total:J}}async function A(z){let D=R("conn"),E=new Date().toISOString();await q.execute(`INSERT INTO integration_connection (id, "integrationId", name, status, credentials, config, "createdAt", "updatedAt")
4
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,[D,z.integrationId,z.name,"PENDING",z.credentials?JSON.stringify(z.credentials):null,z.config?JSON.stringify(z.config):null,E,E]),await q.execute(`UPDATE integration_connection SET status = 'CONNECTED', "updatedAt" = $1 WHERE id = $2`,[E,D]),await q.execute(`UPDATE integration SET status = 'ACTIVE', "updatedAt" = $1 WHERE id = $2`,[E,z.integrationId]);let G=(await q.query("SELECT * FROM integration_connection WHERE id = $1",[D])).rows;return U(G[0])}async function B(z){let D=new Date().toISOString();await q.execute(`UPDATE integration_connection SET status = 'DISCONNECTED', "updatedAt" = $1 WHERE id = $2`,[D,z]);let E=(await q.query("SELECT * FROM integration_connection WHERE id = $1",[z])).rows;return U(E[0])}async function K(z){let{connectionId:D,status:E,limit:G=20,offset:L=0}=z,N="WHERE 1=1",H=[];if(D)N+=` AND "connectionId" = $${H.length+1}`,H.push(D);if(E&&E!=="all")N+=` AND status = $${H.length+1}`,H.push(E);let J=(await q.query(`SELECT COUNT(*) as count FROM integration_sync_config ${N}`,H)).rows[0]?.count??0;return{configs:(await q.query(`SELECT * FROM integration_sync_config ${N} ORDER BY "updatedAt" DESC LIMIT $${H.length+1} OFFSET $${H.length+2}`,[...H,G,L])).rows.map(W),total:J}}async function P(z){let D=R("sync"),E=new Date().toISOString();await q.execute(`INSERT INTO integration_sync_config (id, "connectionId", name, "sourceEntity", "targetEntity", frequency, status, "recordsSynced", "createdAt", "updatedAt")
5
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`,[D,z.connectionId,z.name,z.sourceEntity,z.targetEntity,z.frequency??"DAILY","ACTIVE",0,E,E]);let G=(await q.query("SELECT * FROM integration_sync_config WHERE id = $1",[D])).rows;return W(G[0])}async function O(z){let D=new Date().toISOString(),E=[];await q.execute('DELETE FROM integration_field_mapping WHERE "syncConfigId" = $1',[z.syncConfigId]);for(let G of z.mappings){let L=R("fmap");await q.execute(`INSERT INTO integration_field_mapping (id, "syncConfigId", "sourceField", "targetField", "transformType", "transformConfig", "createdAt")
6
+ VALUES ($1, $2, $3, $4, $5, $6, $7)`,[L,z.syncConfigId,G.sourceField,G.targetField,G.transformType??null,G.transformConfig?JSON.stringify(G.transformConfig):null,D]);let N=(await q.query("SELECT * FROM integration_field_mapping WHERE id = $1",[L])).rows;E.push(Z(N[0]))}return E}async function v(z){return(await q.query('SELECT * FROM integration_field_mapping WHERE "syncConfigId" = $1',[z])).rows.map(Z)}async function M(z){let D=new Date().toISOString(),E=Math.floor(Math.random()*1000)+50;await q.execute(`UPDATE integration_sync_config SET "lastRunAt" = $1, "lastRunStatus" = 'SUCCESS', "recordsSynced" = "recordsSynced" + $2, "updatedAt" = $3 WHERE id = $4`,[D,E,D,z]);let G=(await q.query("SELECT * FROM integration_sync_config WHERE id = $1",[z])).rows;if(G[0])await q.execute('UPDATE integration_connection SET "lastSyncAt" = $1, "updatedAt" = $2 WHERE id = $3',[D,D,G[0].connectionId]);let L=(await q.query("SELECT * FROM integration_sync_config WHERE id = $1",[z])).rows;return W(L[0])}async function V(z){let D=(await q.query("SELECT * FROM integration_connection WHERE id = $1",[z.connectionId])).rows;if(!D[0])return{valid:!1,provider:"unknown",keyPrefix:"",error:`Connection ${z.connectionId} not found`};let E=z.providerKey.slice(0,8),G=z.providerKey.length>=16;return{valid:G,provider:D[0].name,keyPrefix:`${E}...`,expiresAt:G?new Date(Date.now()+7776000000).toISOString():void 0,error:G?void 0:"Key must be at least 16 characters"}}async function F(z){let D=new Date().toISOString();return await q.execute('UPDATE integration_connection SET "updatedAt" = $1 WHERE id = $2',[D,z.connectionId]),{refreshed:!0,expiresAt:new Date(Date.now()+3600000).toISOString(),tokenType:"Bearer",scopes:["read","write","sync"]}}async function k(z){return{integrationId:z.integrationId,transports:[{transport:"rest",supported:!0,defaultVersion:"v2"},{transport:"mcp",supported:!0,defaultVersion:"v1"},{transport:"webhook",supported:!0},{transport:"sdk",supported:!1}]}}return{listIntegrations:_,createIntegration:$,listConnections:j,connectService:A,disconnectService:B,listSyncConfigs:K,configureSync:P,mapFields:O,getFieldMappings:v,runSync:M,validateByokKey:V,refreshOAuth2Token:F,getTransportOptions:k}}export{y as createIntegrationHandlers};
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export * from './example';
8
8
  export { createIntegrationHandlers, type IntegrationHandlers, } from './handlers/integration.handlers';
9
9
  export * from './integration';
10
10
  export * from './mcp-example';
11
+ export * from './setup';
11
12
  export * from './sync';
12
13
  export * from './sync-engine';
13
14
  export * from './ui';
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  // @bun
2
- import{defineEnum as KK}from"@contractspec/lib.schema";var XK=KK("ConnectionStatus",["PENDING","CONNECTED","DISCONNECTED","ERROR","EXPIRED"]),ZK=KK("AuthType",["api_key","oauth2","bearer","header","basic","webhook_signing","service_account"]),$K=KK("TransportType",["rest","mcp","webhook","sdk"]);import{defineSchemaModel as jK,ScalarTypeEnum as N}from"@contractspec/lib.schema";var m=jK({name:"ConnectionModel",fields:{id:{type:N.String_unsecure(),isOptional:!1},integrationId:{type:N.String_unsecure(),isOptional:!1},name:{type:N.String_unsecure(),isOptional:!1},status:{type:XK,isOptional:!1},authType:{type:N.String_unsecure(),isOptional:!1},externalAccountName:{type:N.String_unsecure(),isOptional:!0},connectedAt:{type:N.DateTime(),isOptional:!0},lastHealthCheck:{type:N.DateTime(),isOptional:!0},healthStatus:{type:N.String_unsecure(),isOptional:!0},transport:{type:$K,isOptional:!0},authMethod:{type:ZK,isOptional:!0},apiVersion:{type:N.String_unsecure(),isOptional:!0},ownershipMode:{type:N.String_unsecure(),isOptional:!0}}}),QK=jK({name:"CreateConnectionInput",fields:{integrationId:{type:N.String_unsecure(),isOptional:!1},name:{type:N.NonEmptyString(),isOptional:!1},authType:{type:N.NonEmptyString(),isOptional:!1},credentials:{type:N.JSON(),isOptional:!0},transport:{type:$K,isOptional:!0},authMethod:{type:ZK,isOptional:!0},apiVersion:{type:N.String_unsecure(),isOptional:!0},ownershipMode:{type:N.String_unsecure(),isOptional:!0}}});import{defineCommand as aK}from"@contractspec/lib.contracts-spec/operations";var nK=["@example.integration-hub"],eK=aK({meta:{key:"integration.connection.create",version:"1.0.0",stability:"stable",owners:[...nK],tags:["integration","connection","create"],description:"Create a connection to an external system.",goal:"Authenticate with external systems.",context:"Connection setup."},io:{input:QK,output:m},policy:{auth:"user"},sideEffects:{emits:[{key:"integration.connection.created",version:"1.0.0",when:"Connection created",payload:m}],audit:["integration.connection.created"]},acceptance:{scenarios:[{key:"create-connection-happy-path",given:["User is authenticated"],when:["User creates connection with valid credentials"],then:["Connection is created","ConnectionCreated event is emitted"]}],examples:[{key:"connect-crm",input:{name:"Salesforce Prod",integrationId:"salesforce",credentials:{clientId:"xxx"}},output:{id:"conn-123",status:"connected",connectedAt:"2025-01-01T12:00:00Z"}}]}});import{defineExample as KX}from"@contractspec/lib.contracts-spec/examples";var XX=KX({meta:{key:"examples.integration-hub",version:"1.0.0",title:"Integration Hub",description:"Integration Hub example with sync engine and field mappings for ContractSpec",kind:"template",visibility:"experimental",stability:"experimental",owners:["@contractspec-core"],tags:["package","examples","integration-hub"]},surfaces:{templates:!0,sandbox:{enabled:!0,modes:["playground","specs"]},studio:{enabled:!1,installable:!1},mcp:{enabled:!1}},entrypoints:{packageName:"@contractspec/example.integration-hub"}}),PZ=XX;import{web as ZX}from"@contractspec/lib.runtime-sandbox";var{generateId:p}=ZX;function hK(K){return{id:K.id,projectId:K.projectId,organizationId:K.organizationId,name:K.name,description:K.description??void 0,type:K.type,status:K.status,iconUrl:K.iconUrl??void 0,createdAt:new Date(K.createdAt),updatedAt:new Date(K.updatedAt)}}function qK(K){return{id:K.id,integrationId:K.integrationId,name:K.name,status:K.status,credentials:K.credentials?JSON.parse(K.credentials):void 0,config:K.config?JSON.parse(K.config):void 0,lastSyncAt:K.lastSyncAt?new Date(K.lastSyncAt):void 0,errorMessage:K.errorMessage??void 0,createdAt:new Date(K.createdAt),updatedAt:new Date(K.updatedAt)}}function HK(K){return{id:K.id,connectionId:K.connectionId,name:K.name,sourceEntity:K.sourceEntity,targetEntity:K.targetEntity,frequency:K.frequency,status:K.status,lastRunAt:K.lastRunAt?new Date(K.lastRunAt):void 0,lastRunStatus:K.lastRunStatus??void 0,recordsSynced:K.recordsSynced,createdAt:new Date(K.createdAt),updatedAt:new Date(K.updatedAt)}}function xK(K){return{id:K.id,syncConfigId:K.syncConfigId,sourceField:K.sourceField,targetField:K.targetField,transformType:K.transformType??void 0,transformConfig:K.transformConfig?JSON.parse(K.transformConfig):void 0,createdAt:new Date(K.createdAt)}}function $X(K){async function $(q){let{projectId:Y,type:P,status:B,search:_,limit:z=20,offset:M=0}=q,j="WHERE projectId = ?",f=[Y];if(P&&P!=="all")j+=" AND type = ?",f.push(P);if(B&&B!=="all")j+=" AND status = ?",f.push(B);if(_)j+=" AND name LIKE ?",f.push(`%${_}%`);let sK=(await K.query(`SELECT COUNT(*) as count FROM integration ${j}`,f)).rows[0]?.count??0;return{integrations:(await K.query(`SELECT * FROM integration ${j} ORDER BY name LIMIT ? OFFSET ?`,[...f,z,M])).rows.map(hK),total:sK}}async function X(q,Y){let P=p("integ"),B=new Date().toISOString();await K.execute(`INSERT INTO integration (id, projectId, organizationId, name, description, type, status, iconUrl, createdAt, updatedAt)
3
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[P,Y.projectId,Y.organizationId,q.name,q.description??null,q.type,"INACTIVE",q.iconUrl??null,B,B]);let _=(await K.query("SELECT * FROM integration WHERE id = ?",[P])).rows;return hK(_[0])}async function Z(q){let{integrationId:Y,status:P,limit:B=20,offset:_=0}=q,z="WHERE 1=1",M=[];if(Y)z+=" AND integrationId = ?",M.push(Y);if(P&&P!=="all")z+=" AND status = ?",M.push(P);let f=(await K.query(`SELECT COUNT(*) as count FROM integration_connection ${z}`,M)).rows[0]?.count??0;return{connections:(await K.query(`SELECT * FROM integration_connection ${z} ORDER BY updatedAt DESC LIMIT ? OFFSET ?`,[...M,B,_])).rows.map(qK),total:f}}async function Q(q){let Y=p("conn"),P=new Date().toISOString();await K.execute(`INSERT INTO integration_connection (id, integrationId, name, status, credentials, config, createdAt, updatedAt)
4
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,[Y,q.integrationId,q.name,"PENDING",q.credentials?JSON.stringify(q.credentials):null,q.config?JSON.stringify(q.config):null,P,P]),await K.execute("UPDATE integration_connection SET status = 'CONNECTED', updatedAt = ? WHERE id = ?",[P,Y]),await K.execute("UPDATE integration SET status = 'ACTIVE', updatedAt = ? WHERE id = ?",[P,q.integrationId]);let B=(await K.query("SELECT * FROM integration_connection WHERE id = ?",[Y])).rows;return qK(B[0])}async function H(q){let Y=new Date().toISOString();await K.execute("UPDATE integration_connection SET status = 'DISCONNECTED', updatedAt = ? WHERE id = ?",[Y,q]);let P=(await K.query("SELECT * FROM integration_connection WHERE id = ?",[q])).rows;return qK(P[0])}async function G(q){let{connectionId:Y,status:P,limit:B=20,offset:_=0}=q,z="WHERE 1=1",M=[];if(Y)z+=" AND connectionId = ?",M.push(Y);if(P&&P!=="all")z+=" AND status = ?",M.push(P);let f=(await K.query(`SELECT COUNT(*) as count FROM integration_sync_config ${z}`,M)).rows[0]?.count??0;return{configs:(await K.query(`SELECT * FROM integration_sync_config ${z} ORDER BY updatedAt DESC LIMIT ? OFFSET ?`,[...M,B,_])).rows.map(HK),total:f}}async function W(q){let Y=p("sync"),P=new Date().toISOString();await K.execute(`INSERT INTO integration_sync_config (id, connectionId, name, sourceEntity, targetEntity, frequency, status, recordsSynced, createdAt, updatedAt)
5
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[Y,q.connectionId,q.name,q.sourceEntity,q.targetEntity,q.frequency??"DAILY","ACTIVE",0,P,P]);let B=(await K.query("SELECT * FROM integration_sync_config WHERE id = ?",[Y])).rows;return HK(B[0])}async function A(q){let Y=new Date().toISOString(),P=[];await K.execute("DELETE FROM integration_field_mapping WHERE syncConfigId = ?",[q.syncConfigId]);for(let B of q.mappings){let _=p("fmap");await K.execute(`INSERT INTO integration_field_mapping (id, syncConfigId, sourceField, targetField, transformType, transformConfig, createdAt)
6
- VALUES (?, ?, ?, ?, ?, ?, ?)`,[_,q.syncConfigId,B.sourceField,B.targetField,B.transformType??null,B.transformConfig?JSON.stringify(B.transformConfig):null,Y]);let z=(await K.query("SELECT * FROM integration_field_mapping WHERE id = ?",[_])).rows;P.push(xK(z[0]))}return P}async function O(q){return(await K.query("SELECT * FROM integration_field_mapping WHERE syncConfigId = ?",[q])).rows.map(xK)}async function U(q){let Y=new Date().toISOString(),P=Math.floor(Math.random()*1000)+50;await K.execute("UPDATE integration_sync_config SET lastRunAt = ?, lastRunStatus = 'SUCCESS', recordsSynced = recordsSynced + ?, updatedAt = ? WHERE id = ?",[Y,P,Y,q]);let B=(await K.query("SELECT * FROM integration_sync_config WHERE id = ?",[q])).rows;if(B[0])await K.execute("UPDATE integration_connection SET lastSyncAt = ?, updatedAt = ? WHERE id = ?",[Y,Y,B[0].connectionId]);let _=(await K.query("SELECT * FROM integration_sync_config WHERE id = ?",[q])).rows;return HK(_[0])}async function D(q){let Y=(await K.query("SELECT * FROM integration_connection WHERE id = ?",[q.connectionId])).rows;if(!Y[0])return{valid:!1,provider:"unknown",keyPrefix:"",error:`Connection ${q.connectionId} not found`};let P=q.providerKey.slice(0,8),B=q.providerKey.length>=16;return{valid:B,provider:Y[0].name,keyPrefix:`${P}...`,expiresAt:B?new Date(Date.now()+7776000000).toISOString():void 0,error:B?void 0:"Key must be at least 16 characters"}}async function F(q){let Y=new Date().toISOString();return await K.execute("UPDATE integration_connection SET updatedAt = ? WHERE id = ?",[Y,q.connectionId]),{refreshed:!0,expiresAt:new Date(Date.now()+3600000).toISOString(),tokenType:"Bearer",scopes:["read","write","sync"]}}async function V(q){return{integrationId:q.integrationId,transports:[{transport:"rest",supported:!0,defaultVersion:"v2"},{transport:"mcp",supported:!0,defaultVersion:"v1"},{transport:"webhook",supported:!0},{transport:"sdk",supported:!1}]}}return{listIntegrations:$,createIntegration:X,listConnections:Z,connectService:Q,disconnectService:H,listSyncConfigs:G,configureSync:W,mapFields:A,getFieldMappings:O,runSync:U,validateByokKey:D,refreshOAuth2Token:F,getTransportOptions:V}}import{defineEnum as QX}from"@contractspec/lib.schema";var UK=QX("IntegrationStatus",["DRAFT","ACTIVE","PAUSED","ERROR","ARCHIVED"]);import{defineSchemaModel as EK,ScalarTypeEnum as R}from"@contractspec/lib.schema";var u=EK({name:"IntegrationModel",fields:{id:{type:R.String_unsecure(),isOptional:!1},name:{type:R.String_unsecure(),isOptional:!1},slug:{type:R.String_unsecure(),isOptional:!1},description:{type:R.String_unsecure(),isOptional:!0},provider:{type:R.String_unsecure(),isOptional:!1},status:{type:UK,isOptional:!1},createdAt:{type:R.DateTime(),isOptional:!1}}}),JK=EK({name:"CreateIntegrationInput",fields:{name:{type:R.NonEmptyString(),isOptional:!1},slug:{type:R.NonEmptyString(),isOptional:!1},description:{type:R.String_unsecure(),isOptional:!0},provider:{type:R.NonEmptyString(),isOptional:!1},config:{type:R.JSON(),isOptional:!0},featureFlagKey:{type:R.String_unsecure(),isOptional:!0}}});import{defineCommand as qX}from"@contractspec/lib.contracts-spec/operations";var HX=qX({meta:{key:"integration.create",version:"1.0.0",stability:"stable",owners:["@example.integration-hub"],tags:["integration","create"],description:"Create a new integration.",goal:"Allow users to set up integrations with external systems.",context:"Integration setup."},io:{input:JK,output:u},policy:{auth:"user"},sideEffects:{emits:[{key:"integration.created",version:"1.0.0",when:"Integration created",payload:u}],audit:["integration.created"]},acceptance:{scenarios:[{key:"create-integration-happy-path",given:["User is admin"],when:["User defines new integration type"],then:["Integration definition is created","IntegrationCreated event is emitted"]}],examples:[{key:"create-slack",input:{name:"Slack",category:"communication",authType:"oauth2"},output:{id:"slack",status:"active"}}]}});import{createMcpToolsets as UX}from"@contractspec/lib.ai-agent/tools/mcp-client";import{randomUUID as JX}from"crypto";var YX=["-y","@modelcontextprotocol/server-filesystem","."];async function jZ(){let K=GX(),$=vK(),X=DX(),Z=await UX([X],{onNameCollision:"error"});try{let Q=Object.keys(Z.tools).sort(),H={mode:K,server:{name:X.name,transport:$},authMethod:process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_AUTH_METHOD,apiVersion:process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_API_VERSION,tools:Q};if(K==="call"){let G=wK("CONTRACTSPEC_INTEGRATION_HUB_MCP_TOOL_NAME"),W=WX("CONTRACTSPEC_INTEGRATION_HUB_MCP_TOOL_ARGS_JSON",{}),A=Z.tools[G];if(!A?.execute)throw Error(`Tool "${G}" was not found. Available tools: ${Q.join(", ")}`);let O=await A.execute(W,{toolCallId:`integration-hub-${JX()}`,messages:[]});H.toolCall={name:G,args:W,output:O}}return H}finally{await Z.cleanup().catch(()=>{return})}}function DX(){let K=process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_NAME??"filesystem",$=vK(),X=process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_TOOL_PREFIX;if($==="stdio")return{name:K,transport:$,command:process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_COMMAND??"npx",args:PX("CONTRACTSPEC_INTEGRATION_HUB_MCP_ARGS_JSON",YX),toolPrefix:X};let Z=process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN,Q=process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN_ENV;return{name:K,transport:$==="webhook"||$==="http"?"http":"sse",url:wK("CONTRACTSPEC_INTEGRATION_HUB_MCP_URL"),headers:BX("CONTRACTSPEC_INTEGRATION_HUB_MCP_HEADERS_JSON"),accessToken:Z,accessTokenEnvVar:Q,toolPrefix:X}}function GX(){let K=process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_MODE?.toLowerCase()??"list";if(K==="list"||K==="call")return K;throw Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_MODE: ${K}. Use "list" or "call".`)}function vK(){let K=process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT?.toLowerCase()??"stdio";if(K==="stdio"||K==="http"||K==="sse"||K==="webhook")return K;throw Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT: ${K}. Use "stdio", "http", "sse", or "webhook".`)}function PX(K,$){if(!process.env[K])return $;let Z=TK(K);if(!Array.isArray(Z)||Z.some((Q)=>typeof Q!=="string"))throw Error(`${K} must be a JSON string array.`);return Z}function bK(K){if(!process.env[K])return;let X=TK(K);if(!OX(X))throw Error(`${K} must be a JSON object.`);return X}function WX(K,$){return bK(K)??$}function BX(K){let $=bK(K);if(!$)return;let X=Object.entries($);if(X.find(([,Q])=>typeof Q!=="string"))throw Error(`${K} must contain only string values.`);return Object.fromEntries(X)}function TK(K){let $=process.env[K];if(!$)return;try{return JSON.parse($)}catch{throw Error(`${K} contains invalid JSON.`)}}function wK(K){let $=process.env[K];if(!$)throw Error(`Missing required env var: ${K}`);return $}function OX(K){return typeof K==="object"&&K!==null&&!Array.isArray(K)}import{defineEnum as YK}from"@contractspec/lib.schema";var x=YK("SyncDirection",["INBOUND","OUTBOUND","BIDIRECTIONAL"]),l=YK("SyncStatus",["PENDING","RUNNING","COMPLETED","FAILED","CANCELLED"]),c=YK("MappingType",["DIRECT","TRANSFORM","LOOKUP","CONSTANT","COMPUTED"]);import{defineSchemaModel as C,ScalarTypeEnum as J}from"@contractspec/lib.schema";var b=C({name:"FieldMappingModel",fields:{id:{type:J.String_unsecure(),isOptional:!1},sourceField:{type:J.String_unsecure(),isOptional:!1},targetField:{type:J.String_unsecure(),isOptional:!1},mappingType:{type:c,isOptional:!1},transformExpression:{type:J.String_unsecure(),isOptional:!0},isRequired:{type:J.Boolean(),isOptional:!1}}}),r=C({name:"SyncConfigModel",fields:{id:{type:J.String_unsecure(),isOptional:!1},integrationId:{type:J.String_unsecure(),isOptional:!1},connectionId:{type:J.String_unsecure(),isOptional:!1},name:{type:J.String_unsecure(),isOptional:!1},direction:{type:x,isOptional:!1},sourceObject:{type:J.String_unsecure(),isOptional:!1},targetObject:{type:J.String_unsecure(),isOptional:!1},scheduleEnabled:{type:J.Boolean(),isOptional:!1},scheduleCron:{type:J.String_unsecure(),isOptional:!0},isActive:{type:J.Boolean(),isOptional:!1},lastSyncAt:{type:J.DateTime(),isOptional:!0},fieldMappings:{type:b,isArray:!0,isOptional:!0}}}),T=C({name:"SyncRunModel",fields:{id:{type:J.String_unsecure(),isOptional:!1},syncConfigId:{type:J.String_unsecure(),isOptional:!1},status:{type:l,isOptional:!1},direction:{type:x,isOptional:!1},trigger:{type:J.String_unsecure(),isOptional:!1},recordsProcessed:{type:J.Int_unsecure(),isOptional:!1},recordsCreated:{type:J.Int_unsecure(),isOptional:!1},recordsUpdated:{type:J.Int_unsecure(),isOptional:!1},recordsFailed:{type:J.Int_unsecure(),isOptional:!1},errorMessage:{type:J.String_unsecure(),isOptional:!0},startedAt:{type:J.DateTime(),isOptional:!0},completedAt:{type:J.DateTime(),isOptional:!0},createdAt:{type:J.DateTime(),isOptional:!1}}}),DK=C({name:"CreateSyncConfigInput",fields:{integrationId:{type:J.String_unsecure(),isOptional:!1},connectionId:{type:J.String_unsecure(),isOptional:!1},name:{type:J.NonEmptyString(),isOptional:!1},direction:{type:x,isOptional:!1},sourceObject:{type:J.NonEmptyString(),isOptional:!1},targetObject:{type:J.NonEmptyString(),isOptional:!1},scheduleEnabled:{type:J.Boolean(),isOptional:!0},scheduleCron:{type:J.String_unsecure(),isOptional:!0}}}),GK=C({name:"AddFieldMappingInput",fields:{syncConfigId:{type:J.String_unsecure(),isOptional:!1},sourceField:{type:J.NonEmptyString(),isOptional:!1},targetField:{type:J.NonEmptyString(),isOptional:!1},mappingType:{type:c,isOptional:!1},transformExpression:{type:J.String_unsecure(),isOptional:!0},lookupConfig:{type:J.JSON(),isOptional:!0},constantValue:{type:J.JSON(),isOptional:!0},isRequired:{type:J.Boolean(),isOptional:!0},defaultValue:{type:J.JSON(),isOptional:!0}}}),PK=C({name:"TriggerSyncInput",fields:{syncConfigId:{type:J.String_unsecure(),isOptional:!1},direction:{type:x,isOptional:!0},fullSync:{type:J.Boolean(),isOptional:!0}}}),WK=C({name:"ListSyncRunsInput",fields:{syncConfigId:{type:J.String_unsecure(),isOptional:!1},status:{type:l,isOptional:!0},limit:{type:J.Int_unsecure(),isOptional:!0,defaultValue:20},offset:{type:J.Int_unsecure(),isOptional:!0,defaultValue:0}}}),BK=C({name:"ListSyncRunsOutput",fields:{runs:{type:T,isArray:!0,isOptional:!1},total:{type:J.Int_unsecure(),isOptional:!1}}});import{defineCommand as OK,defineQuery as LX}from"@contractspec/lib.contracts-spec/operations";var i=["@example.integration-hub"],NX=OK({meta:{key:"integration.syncConfig.create",version:"1.0.0",stability:"stable",owners:[...i],tags:["integration","sync","config","create"],description:"Create a sync configuration.",goal:"Define how data should be synchronized.",context:"Sync setup."},io:{input:DK,output:r},policy:{auth:"user"},sideEffects:{emits:[{key:"integration.syncConfig.created",version:"1.0.0",when:"Sync config created",payload:r}],audit:["integration.syncConfig.created"]},acceptance:{scenarios:[{key:"create-sync-happy-path",given:["User is authenticated"],when:["User creates sync config"],then:["Sync config is created","SyncConfigCreated event is emitted"]}],examples:[{key:"create-contact-sync",input:{name:"Contacts Sync",sourceConnectionId:"conn-1",targetConnectionId:"conn-2"},output:{id:"sync-123",status:"active"}}]}}),AX=OK({meta:{key:"integration.fieldMapping.add",version:"1.0.0",stability:"stable",owners:[...i],tags:["integration","mapping","field"],description:"Add a field mapping to a sync config.",goal:"Map fields between systems.",context:"Mapping configuration."},io:{input:GK,output:b},policy:{auth:"user"},sideEffects:{emits:[{key:"integration.fieldMapping.added",version:"1.0.0",when:"Mapping added",payload:b}]},acceptance:{scenarios:[{key:"add-mapping-happy-path",given:["Sync config exists"],when:["User adds field mapping"],then:["Mapping is added","FieldMappingAdded event is emitted"]}],examples:[{key:"map-email",input:{syncConfigId:"sync-123",sourceField:"email",targetField:"user_email"},output:{id:"map-456",type:"string"}}]}}),FX=OK({meta:{key:"integration.sync.trigger",version:"1.0.0",stability:"stable",owners:[...i],tags:["integration","sync","trigger"],description:"Trigger a manual sync.",goal:"Start data synchronization.",context:"Manual sync or webhook trigger."},io:{input:PK,output:T},policy:{auth:"user"},sideEffects:{emits:[{key:"integration.sync.started",version:"1.0.0",when:"Sync starts",payload:T}],audit:["integration.sync.triggered"]},acceptance:{scenarios:[{key:"trigger-sync-happy-path",given:["Sync config exists"],when:["User triggers sync"],then:["Sync run starts","SyncStarted event is emitted"]}],examples:[{key:"manual-trigger",input:{syncConfigId:"sync-123"},output:{id:"run-789",status:"pending"}}]}}),_X=LX({meta:{key:"integration.syncRun.list",version:"1.0.0",stability:"stable",owners:[...i],tags:["integration","sync","run","list"],description:"List sync run history.",goal:"View sync history and status.",context:"Sync monitoring."},io:{input:WK,output:BK},policy:{auth:"user"},acceptance:{scenarios:[{key:"list-runs-happy-path",given:["User has access to syncs"],when:["User lists sync runs"],then:["List of runs is returned"]}],examples:[{key:"list-recent",input:{limit:10},output:{items:[],total:50}}]}});class SK{transform(K,$){try{if($.startsWith("uppercase"))return typeof K==="string"?K.toUpperCase():K;if($.startsWith("lowercase"))return typeof K==="string"?K.toLowerCase():K;if($.startsWith("trim"))return typeof K==="string"?K.trim():K;if($.startsWith("default:")){let X=$.replace("default:","");return K??JSON.parse(X)}if($.startsWith("concat:")){let X=$.replace("concat:","")||" ";if(Array.isArray(K))return K.join(X);return K}if($.startsWith("split:")){let X=$.replace("split:","")||",";if(typeof K==="string")return K.split(X);return K}if($.startsWith("number"))return Number(K);if($.startsWith("boolean"))return Boolean(K);if($.startsWith("string"))return String(K);return K}catch{return K}}}class gK{transformer;constructor(K){this.transformer=K??new SK}async sync(K){return{success:!0,recordsProcessed:0,recordsCreated:0,recordsUpdated:0,recordsDeleted:0,recordsFailed:0,recordsSkipped:0,errors:[]}}transformRecord(K,$,X){let Z={};for(let Q of $){let H,G;switch(Q.mappingType){case"DIRECT":H=this.getNestedValue(K.data,Q.sourceField);break;case"TRANSFORM":G=this.getNestedValue(K.data,Q.sourceField),H=Q.transformExpression?this.transformer.transform(G,Q.transformExpression):G;break;case"CONSTANT":H=Q.constantValue;break;case"LOOKUP":H=this.getNestedValue(K.data,Q.sourceField);break;case"COMPUTED":H=Q.transformExpression?this.evaluateComputed(K.data,Q.transformExpression):null;break;default:H=this.getNestedValue(K.data,Q.sourceField)}if(H===void 0||H===null)H=Q.defaultValue;this.setNestedValue(Z,Q.targetField,H)}return{id:K.id,data:Z}}validateRecord(K,$){let X=[];for(let Z of $)if(Z.isRequired){let Q=this.getNestedValue(K.data,Z.targetField);if(Q===void 0||Q===null)X.push({recordId:K.id,field:Z.targetField,message:`Required field ${Z.targetField} is missing`,code:"REQUIRED_FIELD_MISSING"})}return{valid:X.length===0,errors:X}}getNestedValue(K,$){let X=$.split("."),Z=K;for(let Q of X){if(Z===null||Z===void 0)return;Z=Z[Q]}return Z}setNestedValue(K,$,X){let Z=$.split("."),Q=K;for(let G=0;G<Z.length-1;G++){let W=Z[G];if(W===void 0)continue;if(!(W in Q))Q[W]={};Q=Q[W]}let H=Z[Z.length-1];if(H!==void 0)Q[H]=X}evaluateComputed(K,$){try{return $.replace(/\$\{([^}]+)\}/g,(Z,Q)=>{let H=this.getNestedValue(K,Q);return String(H??"")})}catch{return null}}}function uZ(K){return new gK(K)}function lZ(K){let $=JSON.stringify(K,Object.keys(K).sort()),X=0;for(let Z=0;Z<$.length;Z++){let Q=$.charCodeAt(Z);X=(X<<5)-X+Q,X=X&X}return X.toString(16)}function cZ(K,$){if(!K||!$)return!0;return K!==$}import{useTemplateRuntime as zX}from"@contractspec/lib.example-shared-ui";import{useCallback as RX,useEffect as VX,useState as w}from"react";function LK(K="local-project"){let{handlers:$}=zX(),X=$.integration,[Z,Q]=w([]),[H,G]=w([]),[W,A]=w([]),[O,U]=w(!0),[D,F]=w(null),V=RX(async()=>{try{U(!0),F(null);let[Y,P,B]=await Promise.all([X.listIntegrations({projectId:K,limit:100}),X.listConnections({limit:100}),X.listSyncConfigs({limit:100})]);Q(Y.integrations),G(P.connections),A(B.configs)}catch(Y){F(Y instanceof Error?Y:Error("Failed to load integrations"))}finally{U(!1)}},[X,K]);VX(()=>{V()},[V]);let q={totalIntegrations:Z.length,activeIntegrations:Z.filter((Y)=>Y.status==="ACTIVE").length,totalConnections:H.length,connectedCount:H.filter((Y)=>Y.status==="CONNECTED").length,totalSyncs:W.length,activeSyncs:W.filter((Y)=>Y.status==="ACTIVE").length};return{integrations:Z,connections:H,syncConfigs:W,loading:O,error:D,stats:q,refetch:V}}import{defineVisualization as o,VisualizationRegistry as MX}from"@contractspec/lib.contracts-spec/visualizations";var IX={key:"integration.list",version:"1.0.0"},kX={key:"integration.connection.list",version:"1.0.0"},yK={key:"integration.syncConfig.list",version:"1.0.0"},t={version:"1.0.0",domain:"integration",stability:"experimental",owners:["@example.integration-hub"],tags:["integration","visualization","sync"]},NK=o({meta:{...t,key:"integration-hub.visualization.integration-types",title:"Integration Types",description:"Distribution of configured integration categories.",goal:"Show where integration coverage is concentrated.",context:"Integration overview."},source:{primary:IX,resultPath:"data"},visualization:{kind:"pie",nameDimension:"type",valueMeasure:"count",dimensions:[{key:"type",label:"Type",dataPath:"type",type:"category"}],measures:[{key:"count",label:"Count",dataPath:"count",format:"number"}],table:{caption:"Integration counts by type."}}}),AK=o({meta:{...t,key:"integration-hub.visualization.connection-status",title:"Connection Status",description:"Status distribution across configured connections.",goal:"Highlight connection health and instability.",context:"Connection monitoring."},source:{primary:kX,resultPath:"data"},visualization:{kind:"cartesian",variant:"bar",xDimension:"status",yMeasures:["count"],dimensions:[{key:"status",label:"Status",dataPath:"status",type:"category"}],measures:[{key:"count",label:"Connections",dataPath:"count",format:"number",color:"#1d4ed8"}],table:{caption:"Connection counts by status."}}}),FK=o({meta:{...t,key:"integration-hub.visualization.sync-healthy",title:"Healthy Syncs",description:"Sync configurations currently healthy or recently successful.",goal:"Summarize healthy synchronization capacity.",context:"Sync-state comparison."},source:{primary:yK,resultPath:"data"},visualization:{kind:"metric",measure:"value",measures:[{key:"value",label:"Syncs",dataPath:"value",format:"number"}],table:{caption:"Healthy sync count."}}}),_K=o({meta:{...t,key:"integration-hub.visualization.sync-attention",title:"Attention Needed",description:"Sync configurations paused, failing, or otherwise needing review.",goal:"Summarize syncs needing action.",context:"Sync-state comparison."},source:{primary:yK,resultPath:"data"},visualization:{kind:"metric",measure:"value",measures:[{key:"value",label:"Syncs",dataPath:"value",format:"number"}],table:{caption:"Syncs requiring attention."}}}),dK=[NK,AK,FK,_K],eZ=new MX([...dK]),K0=dK.map((K)=>({key:K.meta.key,version:K.meta.version}));function fX(K){return K==="ACTIVE"||K==="SUCCESS"}function s(K,$,X){let Z=new Map,Q=new Map,H=0,G=0;for(let O of K)Z.set(O.type,(Z.get(O.type)??0)+1);for(let O of $)Q.set(O.status,(Q.get(O.status)??0)+1);for(let O of X)if(fX(O.status))H+=1;else G+=1;return{primaryItems:[{key:"integration-types",spec:NK,data:{data:Array.from(Z.entries()).map(([O,U])=>({type:O,count:U}))},title:"Integration Types",description:"Configured integrations grouped by category.",height:260},{key:"connection-status",spec:AK,data:{data:Array.from(Q.entries()).map(([O,U])=>({status:O,count:U}))},title:"Connection Status",description:"Operational health across current connections."}],comparisonItems:[{key:"healthy-syncs",spec:FK,data:{data:[{value:H}]},title:"Healthy Syncs",description:"Active or recently successful sync configurations.",height:200},{key:"attention-syncs",spec:_K,data:{data:[{value:G}]},title:"Attention Needed",description:"Paused, failed, or degraded sync configurations.",height:200}]}}import{ComparisonView as CX,VisualizationCard as jX,VisualizationGrid as hX}from"@contractspec/lib.design-system";import{jsx as S,jsxs as mK}from"react/jsx-runtime";function pK({integrations:K,connections:$,syncConfigs:X}){let{primaryItems:Z,comparisonItems:Q}=s(K,$,X);return mK("section",{className:"space-y-4",children:[mK("div",{children:[S("h3",{className:"font-semibold text-lg",children:"Integration Visualizations"}),S("p",{className:"text-muted-foreground text-sm",children:"Contract-backed charts for integration coverage and sync health."})]}),S(hX,{children:Z.map((H)=>S(jX,{data:H.data,description:H.description,height:H.height,spec:H.spec,title:H.title},H.key))}),S(CX,{description:"Comparison surface for healthy versus attention-needed syncs.",items:Q,title:"Sync-State Comparison"})]})}import{ChatWithSidebar as xX}from"@contractspec/module.ai-chat";import{jsx as uK}from"react/jsx-runtime";var EX=["List my integrations","Show sync status","Add a connection"],vX="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.";function zK({proxyUrl:K="/api/chat",mcpServers:$,thinkingLevel:X="thinking",suggestions:Z=EX,systemPrompt:Q=vX,className:H}){return uK("div",{className:H??"flex h-[500px] flex-col",children:uK(xX,{className:"flex-1",systemPrompt:Q,proxyUrl:K,mcpServers:$,thinkingLevel:X,suggestions:Z,showSuggestionsWhenEmpty:!0})})}import{Button as a}from"@contractspec/lib.design-system";import{Badge as lK}from"@contractspec/lib.ui-kit-web/ui/badge";import{HStack as bX}from"@contractspec/lib.ui-kit-web/ui/stack";import{jsx as E,jsxs as wX}from"react/jsx-runtime";var TX={ACTIVE:"default",CONNECTED:"default",SUCCESS:"default",PENDING:"secondary",PAUSED:"secondary",ERROR:"destructive",DISCONNECTED:"outline"};function g(K){return K?K.toLocaleString():"Never"}function RK(K){return K?JSON.stringify(K,null,2):"No configuration"}function n({status:K}){return E(lK,{variant:TX[K]??"outline",children:K})}function e({controller:K,label:$,toggleColumnId:X,toggleVisibleLabel:Z,toggleHiddenLabel:Q,pinColumnId:H,pinLabel:G,resizeColumnId:W,resizeLabel:A}){let O=K.rows[0],U=K.columns.find((q)=>q.id===X),D=K.columns.find((q)=>q.id===H),F=K.columns.find((q)=>q.id===W),V=D?.pinState==="left"?!1:"left";return wX(bX,{gap:"sm",className:"flex-wrap",children:[E(lK,{variant:"outline",children:$}),E(a,{variant:"outline",size:"sm",onPress:()=>O?.toggleExpanded?.(!O?.isExpanded),children:"Expand First Row"}),E(a,{variant:"outline",size:"sm",onPress:()=>U?.toggleVisibility?.(!U?.visible),children:U?.visible?Z:Q}),E(a,{variant:"outline",size:"sm",onPress:()=>D?.pin?.(V),children:D?.pinState==="left"?`Unpin ${G}`:`Pin ${G}`}),E(a,{variant:"outline",size:"sm",onPress:()=>F?.resizeBy?.(40),children:A})]})}import{DataTable as SX}from"@contractspec/lib.design-system";import{useContractTable as gX}from"@contractspec/lib.presentation-runtime-react";import{VStack as cK}from"@contractspec/lib.ui-kit-web/ui/stack";import{Text as y}from"@contractspec/lib.ui-kit-web/ui/text";import{jsx as k,jsxs as VK}from"react/jsx-runtime";function MK({connections:K}){let $=gX({data:K,columns:[{id:"connection",header:"Connection",label:"Connection",accessor:(X)=>X.name,cell:({item:X})=>VK(cK,{gap:"xs",children:[k(y,{className:"font-medium text-sm",children:X.name}),VK(y,{className:"text-muted-foreground text-xs",children:["Created ",X.createdAt.toLocaleDateString()]})]}),size:240,minSize:180,canSort:!0,canPin:!0,canResize:!0},{id:"status",header:"Status",label:"Status",accessorKey:"status",cell:({value:X})=>k(n,{status:String(X)}),size:150,canSort:!0,canPin:!0,canResize:!0},{id:"lastSyncAt",header:"Last Sync",label:"Last Sync",accessor:(X)=>X.lastSyncAt?.getTime()??0,cell:({item:X})=>g(X.lastSyncAt),size:200,canSort:!0,canHide:!0,canResize:!0},{id:"errorMessage",header:"Errors",label:"Errors",accessor:(X)=>X.errorMessage??"",cell:({value:X})=>String(X||"No errors"),size:240,canHide:!0,canResize:!0}],initialState:{pagination:{pageIndex:0,pageSize:3},columnVisibility:{errorMessage:!1},columnPinning:{left:["connection"],right:[]}},renderExpandedContent:(X)=>VK(cK,{gap:"sm",className:"py-2",children:[k(y,{className:"font-medium text-sm",children:"Credentials"}),k("pre",{className:"overflow-auto rounded-md bg-muted/40 p-3 text-xs",children:RK(X.credentials)}),k(y,{className:"font-medium text-sm",children:"Config"}),k("pre",{className:"overflow-auto rounded-md bg-muted/40 p-3 text-xs",children:RK(X.config)}),k(y,{className:"text-muted-foreground text-sm",children:X.errorMessage??"No sync errors recorded."})]}),getCanExpand:()=>!0});return k(SX,{controller:$,title:"Connections",description:"Client-mode ContractSpec table with visibility, pinning, resizing, and expanded diagnostics.",toolbar:k(e,{controller:$,label:`${K.length} total connections`,toggleColumnId:"errorMessage",toggleVisibleLabel:"Hide Error Column",toggleHiddenLabel:"Show Error Column",pinColumnId:"status",pinLabel:"Status",resizeColumnId:"connection",resizeLabel:"Widen Connection"}),emptyState:k("div",{className:"rounded-md border border-dashed p-8 text-center text-muted-foreground text-sm",children:"No connections found"})})}import{DataTable as yX}from"@contractspec/lib.design-system";import{useContractTable as dX}from"@contractspec/lib.presentation-runtime-react";import{VStack as rK}from"@contractspec/lib.ui-kit-web/ui/stack";import{Text as v}from"@contractspec/lib.ui-kit-web/ui/text";import{jsx as d,jsxs as h}from"react/jsx-runtime";function IK({syncConfigs:K}){let $=dX({data:K,columns:[{id:"sync",header:"Sync Config",label:"Sync Config",accessor:(X)=>X.name,cell:({item:X})=>h(rK,{gap:"xs",children:[d(v,{className:"font-medium text-sm",children:X.name}),h(v,{className:"text-muted-foreground text-xs",children:[X.sourceEntity," \u2192 ",X.targetEntity]})]}),size:260,minSize:200,canSort:!0,canPin:!0,canResize:!0},{id:"frequency",header:"Frequency",label:"Frequency",accessorKey:"frequency",size:160,canSort:!0,canHide:!0,canResize:!0},{id:"status",header:"Status",label:"Status",accessorKey:"status",cell:({value:X})=>d(n,{status:String(X)}),size:150,canSort:!0,canPin:!0,canResize:!0},{id:"recordsSynced",header:"Records",label:"Records",accessorKey:"recordsSynced",align:"right",size:140,canSort:!0,canResize:!0},{id:"lastRunAt",header:"Last Run",label:"Last Run",accessor:(X)=>X.lastRunAt?.getTime()??0,cell:({item:X})=>g(X.lastRunAt),size:200,canSort:!0,canHide:!0,canResize:!0}],initialState:{pagination:{pageIndex:0,pageSize:3},columnVisibility:{lastRunAt:!1},columnPinning:{left:["sync"],right:[]}},renderExpandedContent:(X)=>h(rK,{gap:"sm",className:"py-2",children:[h(v,{className:"text-muted-foreground text-sm",children:["Connection ",X.connectionId]}),h(v,{className:"text-muted-foreground text-sm",children:["Last run: ",g(X.lastRunAt)]}),h(v,{className:"text-muted-foreground text-sm",children:["Last status: ",X.lastRunStatus??"No runs recorded"]}),h(v,{className:"text-muted-foreground text-sm",children:["Updated ",X.updatedAt.toLocaleString()]})]}),getCanExpand:()=>!0});return d(yX,{controller:$,title:"Sync Configs",description:"Shared table primitives applied to sync monitoring without changing the surrounding dashboard layout.",toolbar:d(e,{controller:$,label:`${K.length} syncs`,toggleColumnId:"lastRunAt",toggleVisibleLabel:"Hide Last Run",toggleHiddenLabel:"Show Last Run",pinColumnId:"status",pinLabel:"Status",resizeColumnId:"sync",resizeLabel:"Widen Sync"}),emptyState:d("div",{className:"rounded-md border border-dashed p-8 text-center text-muted-foreground text-sm",children:"No sync configurations found"})})}import{Button as iK,ErrorState as mX,LoaderBlock as pX,StatCard as kK,StatCardGroup as uX}from"@contractspec/lib.design-system";import{useState as lX}from"react";import{jsx as L,jsxs as I}from"react/jsx-runtime";var cX={ACTIVE:"bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",INACTIVE:"bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400",CONNECTED:"bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",DISCONNECTED:"bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400",PENDING:"bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400",ERROR:"bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",PAUSED:"bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400"},rX={CRM:"\uD83D\uDCCA",MARKETING:"\uD83D\uDCE3",PAYMENT:"\uD83D\uDCB3",COMMUNICATION:"\uD83D\uDCAC",DATA:"\uD83D\uDDC4\uFE0F",CUSTOM:"\u2699\uFE0F"};function iX(){let[K,$]=lX("integrations"),{integrations:X,connections:Z,syncConfigs:Q,loading:H,error:G,stats:W,refetch:A}=LK(),O=[{id:"integrations",label:"Integrations",icon:"\uD83D\uDD0C"},{id:"connections",label:"Connections",icon:"\uD83D\uDD17"},{id:"syncs",label:"Sync Configs",icon:"\uD83D\uDD04"},{id:"chat",label:"Chat",icon:"\uD83D\uDCAC"}];if(H)return L(pX,{label:"Loading Integrations..."});if(G)return L(mX,{title:"Failed to load Integrations",description:G.message,onRetry:A,retryLabel:"Retry"});return I("div",{className:"space-y-6",children:[I("div",{className:"flex items-center justify-between",children:[L("h2",{className:"font-bold text-2xl",children:"Integration Hub"}),I(iK,{onClick:()=>alert("Add integration modal"),children:[L("span",{className:"mr-2",children:"+"})," Add Integration"]})]}),I(uX,{children:[L(kK,{label:"Integrations",value:W.totalIntegrations,hint:`${W.activeIntegrations} active`}),L(kK,{label:"Connections",value:W.totalConnections,hint:`${W.connectedCount} connected`}),L(kK,{label:"Syncs",value:W.totalSyncs,hint:`${W.activeSyncs} active`})]}),L(pK,{connections:Z,integrations:X,syncConfigs:Q}),L("nav",{className:"flex gap-1 rounded-lg bg-muted p-1",role:"tablist",children:O.map((U)=>I(iK,{type:"button",role:"tab","aria-selected":K===U.id,onClick:()=>$(U.id),className:`flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 font-medium text-sm transition-colors ${K===U.id?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"}`,children:[L("span",{children:U.icon}),U.label]},U.id))}),I("div",{className:"min-h-[400px]",role:"tabpanel",children:[K==="integrations"&&I("div",{className:"grid gap-4 sm:grid-cols-2 lg:grid-cols-3",children:[X.map((U)=>I("div",{className:"cursor-pointer rounded-lg border border-border bg-card p-4 transition-colors hover:bg-muted/50",children:[I("div",{className:"mb-3 flex items-center gap-3",children:[L("span",{className:"text-2xl",children:rX[U.type]??"\u2699\uFE0F"}),I("div",{children:[L("h3",{className:"font-medium",children:U.name}),L("p",{className:"text-muted-foreground text-sm",children:U.type})]})]}),I("div",{className:"flex items-center justify-between",children:[L("span",{className:`inline-flex rounded-full px-2 py-0.5 font-medium text-xs ${cX[U.status]??""}`,children:U.status}),L("span",{className:"text-muted-foreground text-xs",children:U.createdAt.toLocaleDateString()})]})]},U.id)),X.length===0&&L("div",{className:"col-span-full flex h-64 items-center justify-center text-muted-foreground",children:"No integrations configured"})]}),K==="connections"&&L(MK,{connections:Z}),K==="chat"&&L(zK,{proxyUrl:"/api/chat",thinkingLevel:"thinking",suggestions:["List my integrations","Show sync status","Add a connection"],className:"min-h-[400px]"}),K==="syncs"&&L(IK,{syncConfigs:Q})]})]})}var oK=[{id:"int-1",name:"Salesforce",type:"CRM",status:"ACTIVE",connectionCount:3},{id:"int-2",name:"HubSpot",type:"MARKETING",status:"ACTIVE",connectionCount:2},{id:"int-3",name:"Stripe",type:"PAYMENT",status:"ACTIVE",connectionCount:1},{id:"int-4",name:"Slack",type:"COMMUNICATION",status:"INACTIVE",connectionCount:0},{id:"int-5",name:"Google Sheets",type:"DATA",status:"ACTIVE",connectionCount:5},{id:"int-6",name:"PostHog",type:"ANALYTICS",status:"ACTIVE",connectionCount:1}],fK=[{id:"conn-1",integrationId:"int-1",name:"Production Salesforce",status:"CONNECTED",lastSyncAt:"2024-01-16T10:00:00Z"},{id:"conn-2",integrationId:"int-1",name:"Sandbox Salesforce",status:"CONNECTED",lastSyncAt:"2024-01-15T14:00:00Z"},{id:"conn-3",integrationId:"int-2",name:"Marketing HubSpot",status:"CONNECTED",lastSyncAt:"2024-01-16T08:00:00Z"},{id:"conn-4",integrationId:"int-3",name:"Stripe Live",status:"CONNECTED",lastSyncAt:"2024-01-16T12:00:00Z"},{id:"conn-5",integrationId:"int-5",name:"Analytics Sheet",status:"ERROR",lastSyncAt:"2024-01-14T09:00:00Z",error:"Authentication expired"},{id:"conn-6",integrationId:"int-6",name:"PostHog Workspace",status:"CONNECTED",lastSyncAt:"2024-01-16T11:45:00Z"}],tK=[{id:"sync-1",connectionId:"conn-1",name:"Contacts Sync",frequency:"HOURLY",lastRunAt:"2024-01-16T10:00:00Z",status:"SUCCESS",recordsSynced:1250},{id:"sync-2",connectionId:"conn-1",name:"Opportunities Sync",frequency:"DAILY",lastRunAt:"2024-01-16T00:00:00Z",status:"SUCCESS",recordsSynced:340},{id:"sync-3",connectionId:"conn-3",name:"Orders Sync",frequency:"REALTIME",lastRunAt:"2024-01-16T12:30:00Z",status:"SUCCESS",recordsSynced:89},{id:"sync-4",connectionId:"conn-5",name:"Metrics Export",frequency:"DAILY",lastRunAt:"2024-01-14T09:00:00Z",status:"FAILED",recordsSynced:0}],oX={target:"markdown",render:async(K)=>{if(K.source.type!=="component"||K.source.componentKey!=="IntegrationDashboard")throw Error("integrationDashboardMarkdownRenderer: not IntegrationDashboard");let $=oK,X=fK,Z=tK,Q=s($,X,Z),H=$.filter((D)=>D.status==="ACTIVE"),G=X.filter((D)=>D.status==="CONNECTED"),W=X.filter((D)=>D.status==="ERROR"),O=Z.filter((D)=>D.status==="SUCCESS").reduce((D,F)=>D+F.recordsSynced,0),U=["# Integration Hub","","> Connect and sync data with external services","","## Overview","","| Metric | Value |","|--------|-------|",`| Active Integrations | ${H.length} |`,`| Connected Services | ${G.length} |`,`| Error Connections | ${W.length} |`,`| Sync Configs | ${Z.length} |`,`| Records Synced (24h) | ${O.toLocaleString()} |`,""];U.push("## Visualization Overview"),U.push("");for(let D of[...Q.primaryItems,...Q.comparisonItems])U.push(`- **${D.title}** via \`${D.spec.meta.key}\``);U.push(""),U.push("## Integrations"),U.push(""),U.push("| Name | Type | Connections | Status |"),U.push("|------|------|-------------|--------|");for(let D of $){let F=D.status==="ACTIVE"?"\uD83D\uDFE2":"\u26AB";U.push(`| ${D.name} | ${D.type} | ${D.connectionCount} | ${F} ${D.status} |`)}U.push(""),U.push("## Recent Sync Activity"),U.push(""),U.push("| Sync | Frequency | Last Run | Records | Status |"),U.push("|------|-----------|----------|---------|--------|");for(let D of Z){let F=new Date(D.lastRunAt).toLocaleString(),V=D.status==="SUCCESS"?"\u2705":"\u274C";U.push(`| ${D.name} | ${D.frequency} | ${F} | ${D.recordsSynced} | ${V} ${D.status} |`)}if(W.length>0){U.push(""),U.push("## \u26A0\uFE0F Connections with Errors"),U.push("");for(let D of W){let F=$.find((V)=>V.id===D.integrationId);U.push(`- **${D.name}** (${F?.name??"Unknown"}): ${D.error??"Unknown error"}`)}}return{mimeType:"text/markdown",body:U.join(`
7
- `)}}},tX={target:"markdown",render:async(K)=>{if(K.source.type!=="component"||K.source.componentKey!=="ConnectionList")throw Error("connectionListMarkdownRenderer: not ConnectionList");let $=fK,X=oK,Z=["# Connections","","> Manage connections to external services",""];for(let Q of X){let H=$.filter((G)=>G.integrationId===Q.id);if(H.length===0)continue;Z.push(`## ${Q.name}`),Z.push(""),Z.push("| Connection | Status | Last Sync |"),Z.push("|------------|--------|-----------|");for(let G of H){let W=new Date(G.lastSyncAt).toLocaleString(),A=G.status==="CONNECTED"?"\uD83D\uDFE2":G.status==="ERROR"?"\uD83D\uDD34":"\u26AB";Z.push(`| ${G.name} | ${A} ${G.status} | ${W} |`)}Z.push("")}return{mimeType:"text/markdown",body:Z.join(`
8
- `)}}},sX={target:"markdown",render:async(K)=>{if(K.source.type!=="component"||K.source.componentKey!=="SyncConfigEditor")throw Error("syncConfigMarkdownRenderer: not SyncConfigEditor");let $=tK,X=fK,Z=["# Sync Configurations","","> Configure automated data synchronization",""];for(let Q of $){let H=X.find((W)=>W.id===Q.connectionId),G=Q.status==="SUCCESS"?"\u2705":"\u274C";Z.push(`## ${Q.name}`),Z.push(""),Z.push(`**Connection:** ${H?.name??"Unknown"}`),Z.push(`**Frequency:** ${Q.frequency}`),Z.push(`**Status:** ${G} ${Q.status}`),Z.push(`**Last Run:** ${new Date(Q.lastRunAt).toLocaleString()}`),Z.push(`**Records Synced:** ${Q.recordsSynced.toLocaleString()}`),Z.push("")}return Z.push("## Frequency Options"),Z.push(""),Z.push("- **REALTIME**: Sync on every change"),Z.push("- **HOURLY**: Sync every hour"),Z.push("- **DAILY**: Sync once per day"),Z.push("- **WEEKLY**: Sync once per week"),Z.push("- **MANUAL**: Sync only when triggered"),{mimeType:"text/markdown",body:Z.join(`
9
- `)}}};export{LK as useIntegrationData,sX as syncConfigMarkdownRenderer,jZ as runIntegrationHubMcpExampleFromEnv,oX as integrationDashboardMarkdownRenderer,cZ as hasChanges,uZ as createSyncEngine,s as createIntegrationVisualizationSections,$X as createIntegrationHandlers,tX as connectionListMarkdownRenderer,lZ as computeChecksum,PK as TriggerSyncInputModel,FX as TriggerSyncContract,l as SyncStatusEnum,T as SyncRunModel,x as SyncDirectionEnum,r as SyncConfigModel,c as MappingTypeEnum,BK as ListSyncRunsOutputModel,WK as ListSyncRunsInputModel,_X as ListSyncRunsContract,dK as IntegrationVisualizationSpecs,eZ as IntegrationVisualizationRegistry,K0 as IntegrationVisualizationRefs,NK as IntegrationTypeVisualization,UK as IntegrationStatusEnum,u as IntegrationModel,zK as IntegrationHubChat,iX as IntegrationDashboard,FK as HealthySyncMetricVisualization,b as FieldMappingModel,XX as ExamplesIntegrationHubExample,DK as CreateSyncConfigInputModel,NX as CreateSyncConfigContract,JK as CreateIntegrationInputModel,HX as CreateIntegrationContract,QK as CreateConnectionInputModel,eK as CreateConnectionContract,AK as ConnectionStatusVisualization,XK as ConnectionStatusEnum,m as ConnectionModel,gK as BasicSyncEngine,SK as BasicFieldTransformer,_K as AttentionSyncMetricVisualization,GK as AddFieldMappingInputModel,AX as AddFieldMappingContract};
2
+ import{defineEnum as YO}from"@contractspec/lib.schema";var XO=YO("ConnectionStatus",["PENDING","CONNECTED","DISCONNECTED","ERROR","EXPIRED"]),BO=YO("AuthType",["api_key","oauth2","bearer","header","basic","webhook_signing","service_account"]),WO=YO("TransportType",["rest","mcp","webhook","sdk"]);import{defineSchemaModel as mO,ScalarTypeEnum as F}from"@contractspec/lib.schema";var i=mO({name:"ConnectionModel",fields:{id:{type:F.String_unsecure(),isOptional:!1},integrationId:{type:F.String_unsecure(),isOptional:!1},name:{type:F.String_unsecure(),isOptional:!1},status:{type:XO,isOptional:!1},authType:{type:F.String_unsecure(),isOptional:!1},externalAccountName:{type:F.String_unsecure(),isOptional:!0},connectedAt:{type:F.DateTime(),isOptional:!0},lastHealthCheck:{type:F.DateTime(),isOptional:!0},healthStatus:{type:F.String_unsecure(),isOptional:!0},transport:{type:WO,isOptional:!0},authMethod:{type:BO,isOptional:!0},apiVersion:{type:F.String_unsecure(),isOptional:!0},ownershipMode:{type:F.String_unsecure(),isOptional:!0}}}),ZO=mO({name:"CreateConnectionInput",fields:{integrationId:{type:F.String_unsecure(),isOptional:!1},name:{type:F.NonEmptyString(),isOptional:!1},authType:{type:F.NonEmptyString(),isOptional:!1},credentials:{type:F.JSON(),isOptional:!0},transport:{type:WO,isOptional:!0},authMethod:{type:BO,isOptional:!0},apiVersion:{type:F.String_unsecure(),isOptional:!0},ownershipMode:{type:F.String_unsecure(),isOptional:!0}}});import{defineCommand as Q_}from"@contractspec/lib.contracts-spec/operations";var D_=["@example.integration-hub"],L_=Q_({meta:{key:"integration.connection.create",version:"1.0.0",stability:"stable",owners:[...D_],tags:["integration","connection","create"],description:"Create a connection to an external system.",goal:"Authenticate with external systems.",context:"Connection setup."},io:{input:ZO,output:i},policy:{auth:"user"},sideEffects:{emits:[{key:"integration.connection.created",version:"1.0.0",when:"Connection created",payload:i}],audit:["integration.connection.created"]},acceptance:{scenarios:[{key:"create-connection-happy-path",given:["User is authenticated"],when:["User creates connection with valid credentials"],then:["Connection is created","ConnectionCreated event is emitted"]}],examples:[{key:"connect-crm",input:{name:"Salesforce Prod",integrationId:"salesforce",credentials:{clientId:"xxx"}},output:{id:"conn-123",status:"connected",connectedAt:"2025-01-01T12:00:00Z"}}]}});import{defineExample as k_}from"@contractspec/lib.contracts-spec/examples";var F_=k_({meta:{key:"examples.integration-hub",version:"1.0.0",title:"Integration Hub",description:"Integration Hub example with sync engine and field mappings for ContractSpec",kind:"template",visibility:"experimental",stability:"experimental",owners:["@contractspec-core"],tags:["package","examples","integration-hub"]},surfaces:{templates:!0,sandbox:{enabled:!0,modes:["playground","specs"]},studio:{enabled:!1,installable:!1},mcp:{enabled:!1}},entrypoints:{packageName:"@contractspec/example.integration-hub"}}),wP=F_;import{web as R_}from"@contractspec/lib.runtime-sandbox";var{generateId:t}=R_;function pO(O){return{id:O.id,projectId:O.projectId,organizationId:O.organizationId,name:O.name,description:O.description??void 0,type:O.type,status:O.status,iconUrl:O.iconUrl??void 0,createdAt:new Date(O.createdAt),updatedAt:new Date(O.updatedAt)}}function $O(O){return{id:O.id,integrationId:O.integrationId,name:O.name,status:O.status,credentials:O.credentials?JSON.parse(O.credentials):void 0,config:O.config?JSON.parse(O.config):void 0,lastSyncAt:O.lastSyncAt?new Date(O.lastSyncAt):void 0,errorMessage:O.errorMessage??void 0,createdAt:new Date(O.createdAt),updatedAt:new Date(O.updatedAt)}}function JO(O){return{id:O.id,connectionId:O.connectionId,name:O.name,sourceEntity:O.sourceEntity,targetEntity:O.targetEntity,frequency:O.frequency,status:O.status,lastRunAt:O.lastRunAt?new Date(O.lastRunAt):void 0,lastRunStatus:O.lastRunStatus??void 0,recordsSynced:O.recordsSynced,createdAt:new Date(O.createdAt),updatedAt:new Date(O.updatedAt)}}function uO(O){return{id:O.id,syncConfigId:O.syncConfigId,sourceField:O.sourceField,targetField:O.targetField,transformType:O.transformType??void 0,transformConfig:O.transformConfig?JSON.parse(O.transformConfig):void 0,createdAt:new Date(O.createdAt)}}function z_(O){async function K(G){let{projectId:X,type:Z,status:Y,search:R,limit:z=20,offset:L=0}=G,E='WHERE "projectId" = $1',I=[X];if(Z&&Z!=="all")E+=` AND type = $${I.length+1}`,I.push(Z);if(Y&&Y!=="all")E+=` AND status = $${I.length+1}`,I.push(Y);if(R)E+=` AND name LIKE $${I.length+1}`,I.push(`%${R}%`);let J_=(await O.query(`SELECT COUNT(*) as count FROM integration ${E}`,I)).rows[0]?.count??0;return{integrations:(await O.query(`SELECT * FROM integration ${E} ORDER BY name LIMIT $${I.length+1} OFFSET $${I.length+2}`,[...I,z,L])).rows.map(pO),total:J_}}async function _(G,X){let Z=t("integ"),Y=new Date().toISOString();await O.execute(`INSERT INTO integration (id, "projectId", "organizationId", name, description, type, status, "iconUrl", "createdAt", "updatedAt")
3
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`,[Z,X.projectId,X.organizationId,G.name,G.description??null,G.type,"INACTIVE",G.iconUrl??null,Y,Y]);let R=(await O.query("SELECT * FROM integration WHERE id = $1",[Z])).rows;return pO(R[0])}async function P(G){let{integrationId:X,status:Z,limit:Y=20,offset:R=0}=G,z="WHERE 1=1",L=[];if(X)z+=` AND "integrationId" = $${L.length+1}`,L.push(X);if(Z&&Z!=="all")z+=` AND status = $${L.length+1}`,L.push(Z);let I=(await O.query(`SELECT COUNT(*) as count FROM integration_connection ${z}`,L)).rows[0]?.count??0;return{connections:(await O.query(`SELECT * FROM integration_connection ${z} ORDER BY "updatedAt" DESC LIMIT $${L.length+1} OFFSET $${L.length+2}`,[...L,Y,R])).rows.map($O),total:I}}async function A(G){let X=t("conn"),Z=new Date().toISOString();await O.execute(`INSERT INTO integration_connection (id, "integrationId", name, status, credentials, config, "createdAt", "updatedAt")
4
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,[X,G.integrationId,G.name,"PENDING",G.credentials?JSON.stringify(G.credentials):null,G.config?JSON.stringify(G.config):null,Z,Z]),await O.execute(`UPDATE integration_connection SET status = 'CONNECTED', "updatedAt" = $1 WHERE id = $2`,[Z,X]),await O.execute(`UPDATE integration SET status = 'ACTIVE', "updatedAt" = $1 WHERE id = $2`,[Z,G.integrationId]);let Y=(await O.query("SELECT * FROM integration_connection WHERE id = $1",[X])).rows;return $O(Y[0])}async function N(G){let X=new Date().toISOString();await O.execute(`UPDATE integration_connection SET status = 'DISCONNECTED', "updatedAt" = $1 WHERE id = $2`,[X,G]);let Z=(await O.query("SELECT * FROM integration_connection WHERE id = $1",[G])).rows;return $O(Z[0])}async function U(G){let{connectionId:X,status:Z,limit:Y=20,offset:R=0}=G,z="WHERE 1=1",L=[];if(X)z+=` AND "connectionId" = $${L.length+1}`,L.push(X);if(Z&&Z!=="all")z+=` AND status = $${L.length+1}`,L.push(Z);let I=(await O.query(`SELECT COUNT(*) as count FROM integration_sync_config ${z}`,L)).rows[0]?.count??0;return{configs:(await O.query(`SELECT * FROM integration_sync_config ${z} ORDER BY "updatedAt" DESC LIMIT $${L.length+1} OFFSET $${L.length+2}`,[...L,Y,R])).rows.map(JO),total:I}}async function Q(G){let X=t("sync"),Z=new Date().toISOString();await O.execute(`INSERT INTO integration_sync_config (id, "connectionId", name, "sourceEntity", "targetEntity", frequency, status, "recordsSynced", "createdAt", "updatedAt")
5
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`,[X,G.connectionId,G.name,G.sourceEntity,G.targetEntity,G.frequency??"DAILY","ACTIVE",0,Z,Z]);let Y=(await O.query("SELECT * FROM integration_sync_config WHERE id = $1",[X])).rows;return JO(Y[0])}async function $(G){let X=new Date().toISOString(),Z=[];await O.execute('DELETE FROM integration_field_mapping WHERE "syncConfigId" = $1',[G.syncConfigId]);for(let Y of G.mappings){let R=t("fmap");await O.execute(`INSERT INTO integration_field_mapping (id, "syncConfigId", "sourceField", "targetField", "transformType", "transformConfig", "createdAt")
6
+ VALUES ($1, $2, $3, $4, $5, $6, $7)`,[R,G.syncConfigId,Y.sourceField,Y.targetField,Y.transformType??null,Y.transformConfig?JSON.stringify(Y.transformConfig):null,X]);let z=(await O.query("SELECT * FROM integration_field_mapping WHERE id = $1",[R])).rows;Z.push(uO(z[0]))}return Z}async function B(G){return(await O.query('SELECT * FROM integration_field_mapping WHERE "syncConfigId" = $1',[G])).rows.map(uO)}async function W(G){let X=new Date().toISOString(),Z=Math.floor(Math.random()*1000)+50;await O.execute(`UPDATE integration_sync_config SET "lastRunAt" = $1, "lastRunStatus" = 'SUCCESS', "recordsSynced" = "recordsSynced" + $2, "updatedAt" = $3 WHERE id = $4`,[X,Z,X,G]);let Y=(await O.query("SELECT * FROM integration_sync_config WHERE id = $1",[G])).rows;if(Y[0])await O.execute('UPDATE integration_connection SET "lastSyncAt" = $1, "updatedAt" = $2 WHERE id = $3',[X,X,Y[0].connectionId]);let R=(await O.query("SELECT * FROM integration_sync_config WHERE id = $1",[G])).rows;return JO(R[0])}async function H(G){let X=(await O.query("SELECT * FROM integration_connection WHERE id = $1",[G.connectionId])).rows;if(!X[0])return{valid:!1,provider:"unknown",keyPrefix:"",error:`Connection ${G.connectionId} not found`};let Z=G.providerKey.slice(0,8),Y=G.providerKey.length>=16;return{valid:Y,provider:X[0].name,keyPrefix:`${Z}...`,expiresAt:Y?new Date(Date.now()+7776000000).toISOString():void 0,error:Y?void 0:"Key must be at least 16 characters"}}async function J(G){let X=new Date().toISOString();return await O.execute('UPDATE integration_connection SET "updatedAt" = $1 WHERE id = $2',[X,G.connectionId]),{refreshed:!0,expiresAt:new Date(Date.now()+3600000).toISOString(),tokenType:"Bearer",scopes:["read","write","sync"]}}async function v(G){return{integrationId:G.integrationId,transports:[{transport:"rest",supported:!0,defaultVersion:"v2"},{transport:"mcp",supported:!0,defaultVersion:"v1"},{transport:"webhook",supported:!0},{transport:"sdk",supported:!1}]}}return{listIntegrations:K,createIntegration:_,listConnections:P,connectService:A,disconnectService:N,listSyncConfigs:U,configureSync:Q,mapFields:$,getFieldMappings:B,runSync:W,validateByokKey:H,refreshOAuth2Token:J,getTransportOptions:v}}import{defineEnum as I_}from"@contractspec/lib.schema";var QO=I_("IntegrationStatus",["DRAFT","ACTIVE","PAUSED","ERROR","ARCHIVED"]);import{defineSchemaModel as rO,ScalarTypeEnum as V}from"@contractspec/lib.schema";var s=rO({name:"IntegrationModel",fields:{id:{type:V.String_unsecure(),isOptional:!1},name:{type:V.String_unsecure(),isOptional:!1},slug:{type:V.String_unsecure(),isOptional:!1},description:{type:V.String_unsecure(),isOptional:!0},provider:{type:V.String_unsecure(),isOptional:!1},status:{type:QO,isOptional:!1},createdAt:{type:V.DateTime(),isOptional:!1}}}),DO=rO({name:"CreateIntegrationInput",fields:{name:{type:V.NonEmptyString(),isOptional:!1},slug:{type:V.NonEmptyString(),isOptional:!1},description:{type:V.String_unsecure(),isOptional:!0},provider:{type:V.NonEmptyString(),isOptional:!1},config:{type:V.JSON(),isOptional:!0},featureFlagKey:{type:V.String_unsecure(),isOptional:!0}}});import{defineCommand as V_}from"@contractspec/lib.contracts-spec/operations";var M_=V_({meta:{key:"integration.create",version:"1.0.0",stability:"stable",owners:["@example.integration-hub"],tags:["integration","create"],description:"Create a new integration.",goal:"Allow users to set up integrations with external systems.",context:"Integration setup."},io:{input:DO,output:s},policy:{auth:"user"},sideEffects:{emits:[{key:"integration.created",version:"1.0.0",when:"Integration created",payload:s}],audit:["integration.created"]},acceptance:{scenarios:[{key:"create-integration-happy-path",given:["User is admin"],when:["User defines new integration type"],then:["Integration definition is created","IntegrationCreated event is emitted"]}],examples:[{key:"create-slack",input:{name:"Slack",category:"communication",authType:"oauth2"},output:{id:"slack",status:"active"}}]}});import{createMcpToolsets as C_}from"@contractspec/lib.ai-agent/tools/mcp-client";import{randomUUID as h_}from"crypto";var f_=["-y","@modelcontextprotocol/server-filesystem","."];async function sP(){let O=b_(),K=lO(),_=v_(),P=await C_([_],{onNameCollision:"error"});try{let A=Object.keys(P.tools).sort(),N={mode:O,server:{name:_.name,transport:K},authMethod:process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_AUTH_METHOD,apiVersion:process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_API_VERSION,tools:A};if(O==="call"){let U=iO("CONTRACTSPEC_INTEGRATION_HUB_MCP_TOOL_NAME"),Q=w_("CONTRACTSPEC_INTEGRATION_HUB_MCP_TOOL_ARGS_JSON",{}),$=P.tools[U];if(!$?.execute)throw Error(`Tool "${U}" was not found. Available tools: ${A.join(", ")}`);let B=await $.execute(Q,{toolCallId:`integration-hub-${h_()}`,messages:[]});N.toolCall={name:U,args:Q,output:B}}return N}finally{await P.cleanup().catch(()=>{return})}}function v_(){let O=process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_NAME??"filesystem",K=lO(),_=process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_TOOL_PREFIX;if(K==="stdio")return{name:O,transport:K,command:process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_COMMAND??"npx",args:E_("CONTRACTSPEC_INTEGRATION_HUB_MCP_ARGS_JSON",f_),toolPrefix:_};let P=process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN,A=process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_ACCESS_TOKEN_ENV;return{name:O,transport:K==="webhook"||K==="http"?"http":"sse",url:iO("CONTRACTSPEC_INTEGRATION_HUB_MCP_URL"),headers:j_("CONTRACTSPEC_INTEGRATION_HUB_MCP_HEADERS_JSON"),accessToken:P,accessTokenEnvVar:A,toolPrefix:_}}function b_(){let O=process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_MODE?.toLowerCase()??"list";if(O==="list"||O==="call")return O;throw Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_MODE: ${O}. Use "list" or "call".`)}function lO(){let O=process.env.CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT?.toLowerCase()??"stdio";if(O==="stdio"||O==="http"||O==="sse"||O==="webhook")return O;throw Error(`Unsupported CONTRACTSPEC_INTEGRATION_HUB_MCP_TRANSPORT: ${O}. Use "stdio", "http", "sse", or "webhook".`)}function E_(O,K){if(!process.env[O])return K;let P=oO(O);if(!Array.isArray(P)||P.some((A)=>typeof A!=="string"))throw Error(`${O} must be a JSON string array.`);return P}function cO(O){if(!process.env[O])return;let _=oO(O);if(!x_(_))throw Error(`${O} must be a JSON object.`);return _}function w_(O,K){return cO(O)??K}function j_(O){let K=cO(O);if(!K)return;let _=Object.entries(K);if(_.find(([,A])=>typeof A!=="string"))throw Error(`${O} must contain only string values.`);return Object.fromEntries(_)}function oO(O){let K=process.env[O];if(!K)return;try{return JSON.parse(K)}catch{throw Error(`${O} contains invalid JSON.`)}}function iO(O){let K=process.env[O];if(!K)throw Error(`Missing required env var: ${O}`);return K}function x_(O){return typeof O==="object"&&O!==null&&!Array.isArray(O)}var tO={modes:{managed:{mode:"managed",configFields:[{key:"workspaceId",required:!0,description:"Managed ContractSpec workspace that owns the provider connection."},{key:"region",required:!0,description:"Provider region used by the managed connector runtime."}],validationStrategy:"provider-health",setupSteps:["Select the workspace-owned managed connector.","Run the provider health check before enabling sync jobs."]},byok:{mode:"byok",configFields:[{key:"projectApiKey",required:!0,envVar:"POSTHOG_PROJECT_API_KEY",description:"Public analytics project key exposed through app-specific aliases."}],secretFields:[{key:"personalApiKey",required:!0,envVar:"POSTHOG_PERSONAL_API_KEY",description:"Server-only BYOK secret used for provider administration calls."},{key:"webhookSecret",required:!0,envVar:"INTEGRATION_HUB_WEBHOOK_SECRET",description:"Server-only signing secret for incoming integration webhooks."}],validationStrategy:"byok-lifecycle",rotation:{supported:!0,recommendedIntervalDays:90},allowedSecretProviders:["env","vault","vercel","doppler"],setupSteps:["Create a restricted provider key with read/write access for sync metadata.","Store the key through a secret reference, never as a raw value in app config.","Materialize only public config aliases into browser or native app bundles."]}}},sO={targets:{webConsole:{id:"webConsole",packageName:"@acme/integration-web",packagePath:"apps/web",framework:"next",surfaces:["server","public-client"],envFiles:["apps/web/.env.local"]},mobileConsole:{id:"mobileConsole",packageName:"@acme/integration-mobile",packagePath:"apps/mobile",framework:"expo",surfaces:["native-client"],envFiles:["apps/mobile/.env"]},syncWorker:{id:"syncWorker",packageName:"@acme/integration-worker",packagePath:"apps/worker",framework:"node",surfaces:["server","worker"],envFiles:["apps/worker/.env"]}},variables:{publicOrigin:{key:"publicOrigin",description:"Origin shared by web and mobile clients for integration callbacks.",sensitivity:"public",allowedSurfaces:["public-client","native-client"],aliases:[{targetId:"webConsole",framework:"next",name:"NEXT_PUBLIC_INTEGRATION_HUB_ORIGIN",exposure:"public-client"},{targetId:"mobileConsole",framework:"expo",name:"EXPO_PUBLIC_INTEGRATION_HUB_ORIGIN",exposure:"native-client"}]},projectApiKey:{key:"projectApiKey",description:"Public analytics key scoped to product usage capture.",sensitivity:"public",allowedSurfaces:["public-client","native-client"],valueSource:{type:"byok-connection",connectionId:"conn_posthog"},aliases:[{targetId:"webConsole",framework:"next",name:"NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY",exposure:"public-client"},{targetId:"mobileConsole",framework:"expo",name:"EXPO_PUBLIC_POSTHOG_PROJECT_API_KEY",exposure:"native-client"}]},personalApiKey:{key:"personalApiKey",description:"Server-only provider administration token.",sensitivity:"secret",allowedSurfaces:["server","worker"],valueSource:{type:"secret",secretRef:"env://POSTHOG_PERSONAL_API_KEY"},aliases:[{targetId:"syncWorker",framework:"node",name:"POSTHOG_PERSONAL_API_KEY",exposure:"server"}]},webhookSecret:{key:"webhookSecret",description:"Server-only secret for validating provider webhooks.",sensitivity:"secret",allowedSurfaces:["server","worker"],aliases:[{targetId:"syncWorker",framework:"node",name:"INTEGRATION_HUB_WEBHOOK_SECRET",exposure:"server"}]}},secretRequirements:{personalApiKey:{key:"personalApiKey",required:!0,envVar:"POSTHOG_PERSONAL_API_KEY",provider:"env",rotationDays:90},webhookSecret:{key:"webhookSecret",required:!0,envVar:"INTEGRATION_HUB_WEBHOOK_SECRET",provider:"env",rotationDays:90}}},e={selectedMode:"byok",targetIds:["webConsole","mobileConsole","syncWorker"],configValues:{projectApiKey:"public-project-key-ref"},secretRefs:{personalApiKey:"env://POSTHOG_PERSONAL_API_KEY"}};import{defineEnum as LO}from"@contractspec/lib.schema";var j=LO("SyncDirection",["INBOUND","OUTBOUND","BIDIRECTIONAL"]),a=LO("SyncStatus",["PENDING","RUNNING","COMPLETED","FAILED","CANCELLED"]),n=LO("MappingType",["DIRECT","TRANSFORM","LOOKUP","CONSTANT","COMPUTED"]);import{defineSchemaModel as b,ScalarTypeEnum as q}from"@contractspec/lib.schema";var y=b({name:"FieldMappingModel",fields:{id:{type:q.String_unsecure(),isOptional:!1},sourceField:{type:q.String_unsecure(),isOptional:!1},targetField:{type:q.String_unsecure(),isOptional:!1},mappingType:{type:n,isOptional:!1},transformExpression:{type:q.String_unsecure(),isOptional:!0},isRequired:{type:q.Boolean(),isOptional:!1}}}),OO=b({name:"SyncConfigModel",fields:{id:{type:q.String_unsecure(),isOptional:!1},integrationId:{type:q.String_unsecure(),isOptional:!1},connectionId:{type:q.String_unsecure(),isOptional:!1},name:{type:q.String_unsecure(),isOptional:!1},direction:{type:j,isOptional:!1},sourceObject:{type:q.String_unsecure(),isOptional:!1},targetObject:{type:q.String_unsecure(),isOptional:!1},scheduleEnabled:{type:q.Boolean(),isOptional:!1},scheduleCron:{type:q.String_unsecure(),isOptional:!0},isActive:{type:q.Boolean(),isOptional:!1},lastSyncAt:{type:q.DateTime(),isOptional:!0},fieldMappings:{type:y,isArray:!0,isOptional:!0}}}),d=b({name:"SyncRunModel",fields:{id:{type:q.String_unsecure(),isOptional:!1},syncConfigId:{type:q.String_unsecure(),isOptional:!1},status:{type:a,isOptional:!1},direction:{type:j,isOptional:!1},trigger:{type:q.String_unsecure(),isOptional:!1},recordsProcessed:{type:q.Int_unsecure(),isOptional:!1},recordsCreated:{type:q.Int_unsecure(),isOptional:!1},recordsUpdated:{type:q.Int_unsecure(),isOptional:!1},recordsFailed:{type:q.Int_unsecure(),isOptional:!1},errorMessage:{type:q.String_unsecure(),isOptional:!0},startedAt:{type:q.DateTime(),isOptional:!0},completedAt:{type:q.DateTime(),isOptional:!0},createdAt:{type:q.DateTime(),isOptional:!1}}}),kO=b({name:"CreateSyncConfigInput",fields:{integrationId:{type:q.String_unsecure(),isOptional:!1},connectionId:{type:q.String_unsecure(),isOptional:!1},name:{type:q.NonEmptyString(),isOptional:!1},direction:{type:j,isOptional:!1},sourceObject:{type:q.NonEmptyString(),isOptional:!1},targetObject:{type:q.NonEmptyString(),isOptional:!1},scheduleEnabled:{type:q.Boolean(),isOptional:!0},scheduleCron:{type:q.String_unsecure(),isOptional:!0}}}),FO=b({name:"AddFieldMappingInput",fields:{syncConfigId:{type:q.String_unsecure(),isOptional:!1},sourceField:{type:q.NonEmptyString(),isOptional:!1},targetField:{type:q.NonEmptyString(),isOptional:!1},mappingType:{type:n,isOptional:!1},transformExpression:{type:q.String_unsecure(),isOptional:!0},lookupConfig:{type:q.JSON(),isOptional:!0},constantValue:{type:q.JSON(),isOptional:!0},isRequired:{type:q.Boolean(),isOptional:!0},defaultValue:{type:q.JSON(),isOptional:!0}}}),RO=b({name:"TriggerSyncInput",fields:{syncConfigId:{type:q.String_unsecure(),isOptional:!1},direction:{type:j,isOptional:!0},fullSync:{type:q.Boolean(),isOptional:!0}}}),zO=b({name:"ListSyncRunsInput",fields:{syncConfigId:{type:q.String_unsecure(),isOptional:!1},status:{type:a,isOptional:!0},limit:{type:q.Int_unsecure(),isOptional:!0,defaultValue:20},offset:{type:q.Int_unsecure(),isOptional:!0,defaultValue:0}}}),IO=b({name:"ListSyncRunsOutput",fields:{runs:{type:d,isArray:!0,isOptional:!1},total:{type:q.Int_unsecure(),isOptional:!1}}});import{defineCommand as VO,defineQuery as T_}from"@contractspec/lib.contracts-spec/operations";var _O=["@example.integration-hub"],g_=VO({meta:{key:"integration.syncConfig.create",version:"1.0.0",stability:"stable",owners:[..._O],tags:["integration","sync","config","create"],description:"Create a sync configuration.",goal:"Define how data should be synchronized.",context:"Sync setup."},io:{input:kO,output:OO},policy:{auth:"user"},sideEffects:{emits:[{key:"integration.syncConfig.created",version:"1.0.0",when:"Sync config created",payload:OO}],audit:["integration.syncConfig.created"]},acceptance:{scenarios:[{key:"create-sync-happy-path",given:["User is authenticated"],when:["User creates sync config"],then:["Sync config is created","SyncConfigCreated event is emitted"]}],examples:[{key:"create-contact-sync",input:{name:"Contacts Sync",sourceConnectionId:"conn-1",targetConnectionId:"conn-2"},output:{id:"sync-123",status:"active"}}]}}),S_=VO({meta:{key:"integration.fieldMapping.add",version:"1.0.0",stability:"stable",owners:[..._O],tags:["integration","mapping","field"],description:"Add a field mapping to a sync config.",goal:"Map fields between systems.",context:"Mapping configuration."},io:{input:FO,output:y},policy:{auth:"user"},sideEffects:{emits:[{key:"integration.fieldMapping.added",version:"1.0.0",when:"Mapping added",payload:y}]},acceptance:{scenarios:[{key:"add-mapping-happy-path",given:["Sync config exists"],when:["User adds field mapping"],then:["Mapping is added","FieldMappingAdded event is emitted"]}],examples:[{key:"map-email",input:{syncConfigId:"sync-123",sourceField:"email",targetField:"user_email"},output:{id:"map-456",type:"string"}}]}}),y_=VO({meta:{key:"integration.sync.trigger",version:"1.0.0",stability:"stable",owners:[..._O],tags:["integration","sync","trigger"],description:"Trigger a manual sync.",goal:"Start data synchronization.",context:"Manual sync or webhook trigger."},io:{input:RO,output:d},policy:{auth:"user"},sideEffects:{emits:[{key:"integration.sync.started",version:"1.0.0",when:"Sync starts",payload:d}],audit:["integration.sync.triggered"]},acceptance:{scenarios:[{key:"trigger-sync-happy-path",given:["Sync config exists"],when:["User triggers sync"],then:["Sync run starts","SyncStarted event is emitted"]}],examples:[{key:"manual-trigger",input:{syncConfigId:"sync-123"},output:{id:"run-789",status:"pending"}}]}}),d_=T_({meta:{key:"integration.syncRun.list",version:"1.0.0",stability:"stable",owners:[..._O],tags:["integration","sync","run","list"],description:"List sync run history.",goal:"View sync history and status.",context:"Sync monitoring."},io:{input:zO,output:IO},policy:{auth:"user"},acceptance:{scenarios:[{key:"list-runs-happy-path",given:["User has access to syncs"],when:["User lists sync runs"],then:["List of runs is returned"]}],examples:[{key:"list-recent",input:{limit:10},output:{items:[],total:50}}]}});class eO{transform(O,K){try{if(K.startsWith("uppercase"))return typeof O==="string"?O.toUpperCase():O;if(K.startsWith("lowercase"))return typeof O==="string"?O.toLowerCase():O;if(K.startsWith("trim"))return typeof O==="string"?O.trim():O;if(K.startsWith("default:")){let _=K.replace("default:","");return O??JSON.parse(_)}if(K.startsWith("concat:")){let _=K.replace("concat:","")||" ";if(Array.isArray(O))return O.join(_);return O}if(K.startsWith("split:")){let _=K.replace("split:","")||",";if(typeof O==="string")return O.split(_);return O}if(K.startsWith("number"))return Number(O);if(K.startsWith("boolean"))return Boolean(O);if(K.startsWith("string"))return String(O);return O}catch{return O}}}class aO{transformer;constructor(O){this.transformer=O??new eO}async sync(O){return{success:!0,recordsProcessed:0,recordsCreated:0,recordsUpdated:0,recordsDeleted:0,recordsFailed:0,recordsSkipped:0,errors:[]}}transformRecord(O,K,_){let P={};for(let A of K){let N,U;switch(A.mappingType){case"DIRECT":N=this.getNestedValue(O.data,A.sourceField);break;case"TRANSFORM":U=this.getNestedValue(O.data,A.sourceField),N=A.transformExpression?this.transformer.transform(U,A.transformExpression):U;break;case"CONSTANT":N=A.constantValue;break;case"LOOKUP":N=this.getNestedValue(O.data,A.sourceField);break;case"COMPUTED":N=A.transformExpression?this.evaluateComputed(O.data,A.transformExpression):null;break;default:N=this.getNestedValue(O.data,A.sourceField)}if(N===void 0||N===null)N=A.defaultValue;this.setNestedValue(P,A.targetField,N)}return{id:O.id,data:P}}validateRecord(O,K){let _=[];for(let P of K)if(P.isRequired){let A=this.getNestedValue(O.data,P.targetField);if(A===void 0||A===null)_.push({recordId:O.id,field:P.targetField,message:`Required field ${P.targetField} is missing`,code:"REQUIRED_FIELD_MISSING"})}return{valid:_.length===0,errors:_}}getNestedValue(O,K){let _=K.split("."),P=O;for(let A of _){if(P===null||P===void 0)return;P=P[A]}return P}setNestedValue(O,K,_){let P=K.split("."),A=O;for(let U=0;U<P.length-1;U++){let Q=P[U];if(Q===void 0)continue;if(!(Q in A))A[Q]={};A=A[Q]}let N=P[P.length-1];if(N!==void 0)A[N]=_}evaluateComputed(O,K){try{return K.replace(/\$\{([^}]+)\}/g,(P,A)=>{let N=this.getNestedValue(O,A);return String(N??"")})}catch{return null}}}function WK(O){return new aO(O)}function ZK(O){let K=JSON.stringify(O,Object.keys(O).sort()),_=0;for(let P=0;P<K.length;P++){let A=K.charCodeAt(P);_=(_<<5)-_+A,_=_&_}return _.toString(16)}function $K(O,K){if(!O||!K)return!0;return O!==K}import{useTemplateRuntime as m_}from"@contractspec/lib.example-shared-ui";import{useCallback as p_,useEffect as u_,useState as m}from"react";function MO(O){let{handlers:K,projectId:_}=m_(),P=K.integration,A=O??_,[N,U]=m([]),[Q,$]=m([]),[B,W]=m([]),[H,J]=m(!0),[v,G]=m(null),X=p_(async()=>{try{J(!0),G(null);let[Y,R,z]=await Promise.all([P.listIntegrations({projectId:A,limit:100}),P.listConnections({limit:100}),P.listSyncConfigs({limit:100})]);U(Y.integrations),$(R.connections),W(z.configs)}catch(Y){G(Y instanceof Error?Y:Error("Failed to load integrations"))}finally{J(!1)}},[A,P]);u_(()=>{X()},[X]);let Z={totalIntegrations:N.length,activeIntegrations:N.filter((Y)=>Y.status==="ACTIVE").length,totalConnections:Q.length,connectedCount:Q.filter((Y)=>Y.status==="CONNECTED").length,totalSyncs:B.length,activeSyncs:B.filter((Y)=>Y.status==="ACTIVE").length};return{integrations:N,connections:Q,syncConfigs:B,loading:H,error:v,stats:Z,refetch:X}}import{defineVisualization as PO,VisualizationRegistry as r_}from"@contractspec/lib.contracts-spec/visualizations";var l_={key:"integration.list",version:"1.0.0"},c_={key:"integration.connection.list",version:"1.0.0"},nO={key:"integration.syncConfig.list",version:"1.0.0"},KO={version:"1.0.0",domain:"integration",stability:"experimental",owners:["@example.integration-hub"],tags:["integration","visualization","sync"]},CO=PO({meta:{...KO,key:"integration-hub.visualization.integration-types",title:"Integration Types",description:"Distribution of configured integration categories.",goal:"Show where integration coverage is concentrated.",context:"Integration overview."},source:{primary:l_,resultPath:"data"},visualization:{kind:"pie",nameDimension:"type",valueMeasure:"count",dimensions:[{key:"type",label:"Type",dataPath:"type",type:"category"}],measures:[{key:"count",label:"Count",dataPath:"count",format:"number"}],table:{caption:"Integration counts by type."}}}),hO=PO({meta:{...KO,key:"integration-hub.visualization.connection-status",title:"Connection Status",description:"Status distribution across configured connections.",goal:"Highlight connection health and instability.",context:"Connection monitoring."},source:{primary:c_,resultPath:"data"},visualization:{kind:"cartesian",variant:"bar",xDimension:"status",yMeasures:["count"],dimensions:[{key:"status",label:"Status",dataPath:"status",type:"category"}],measures:[{key:"count",label:"Connections",dataPath:"count",format:"number",color:"#1d4ed8"}],table:{caption:"Connection counts by status."}}}),fO=PO({meta:{...KO,key:"integration-hub.visualization.sync-healthy",title:"Healthy Syncs",description:"Sync configurations currently healthy or recently successful.",goal:"Summarize healthy synchronization capacity.",context:"Sync-state comparison."},source:{primary:nO,resultPath:"data"},visualization:{kind:"metric",measure:"value",measures:[{key:"value",label:"Syncs",dataPath:"value",format:"number"}],table:{caption:"Healthy sync count."}}}),vO=PO({meta:{...KO,key:"integration-hub.visualization.sync-attention",title:"Attention Needed",description:"Sync configurations paused, failing, or otherwise needing review.",goal:"Summarize syncs needing action.",context:"Sync-state comparison."},source:{primary:nO,resultPath:"data"},visualization:{kind:"metric",measure:"value",measures:[{key:"value",label:"Syncs",dataPath:"value",format:"number"}],table:{caption:"Syncs requiring attention."}}}),O_=[CO,hO,fO,vO],zK=new r_([...O_]),IK=O_.map((O)=>({key:O.meta.key,version:O.meta.version}));function o_(O){return O==="ACTIVE"||O==="SUCCESS"}function AO(O,K,_){let P=new Map,A=new Map,N=0,U=0;for(let B of O)P.set(B.type,(P.get(B.type)??0)+1);for(let B of K)A.set(B.status,(A.get(B.status)??0)+1);for(let B of _)if(o_(B.status))N+=1;else U+=1;return{primaryItems:[{key:"integration-types",spec:CO,data:{data:Array.from(P.entries()).map(([B,W])=>({type:B,count:W}))},title:"Integration Types",description:"Configured integrations grouped by category.",height:260},{key:"connection-status",spec:hO,data:{data:Array.from(A.entries()).map(([B,W])=>({status:B,count:W}))},title:"Connection Status",description:"Operational health across current connections."}],comparisonItems:[{key:"healthy-syncs",spec:fO,data:{data:[{value:N}]},title:"Healthy Syncs",description:"Active or recently successful sync configurations.",height:200},{key:"attention-syncs",spec:vO,data:{data:[{value:U}]},title:"Attention Needed",description:"Paused, failed, or degraded sync configurations.",height:200}]}}import{ComparisonView as i_,VisualizationCard as t_,VisualizationGrid as s_}from"@contractspec/lib.design-system";import{jsx as p,jsxs as __}from"react/jsx-runtime";function P_({integrations:O,connections:K,syncConfigs:_}){let{primaryItems:P,comparisonItems:A}=AO(O,K,_);return __("section",{className:"space-y-4",children:[__("div",{children:[p("h3",{className:"font-semibold text-lg",children:"Integration Visualizations"}),p("p",{className:"text-muted-foreground text-sm",children:"Contract-backed charts for integration coverage and sync health."})]}),p(s_,{children:P.map((N)=>p(t_,{data:N.data,description:N.description,height:N.height,spec:N.spec,title:N.title},N.key))}),p(i_,{description:"Comparison surface for healthy versus attention-needed syncs.",items:A,title:"Sync-State Comparison"})]})}import{ChatWithSidebar as e_}from"@contractspec/module.ai-chat";import{jsx as K_}from"react/jsx-runtime";var a_=["List my integrations","Show sync status","Add a connection"],n_="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.";function bO({proxyUrl:O="/api/chat",mcpServers:K,thinkingLevel:_="thinking",suggestions:P=a_,systemPrompt:A=n_,className:N}){return K_("div",{className:N??"flex h-[500px] flex-col",children:K_(e_,{className:"flex-1",systemPrompt:A,proxyUrl:O,mcpServers:K,thinkingLevel:_,suggestions:P,showSuggestionsWhenEmpty:!0})})}function N_(O){let K=tO,_=sO,P=e,A=K.modes?.[O],N=[...(A?.configFields??[]).map(($)=>({...$,kind:"config",configured:A_(P.configValues[$.key]),secretRef:void 0})),...(A?.secretFields??[]).map(($)=>({...$,kind:"secret",configured:A_(P.secretRefs[$.key]),secretRef:P.secretRefs[$.key]}))],U=Object.values(_.variables??{}).flatMap(($)=>($.aliases??[]).map((B)=>({...B,targetLabel:_.targets?.[B.targetId??""]?.packageName??B.targetId}))).filter(($)=>P.targetIds.includes($.targetId??"")),Q=N.filter(($)=>$.kind==="secret"&&$.required&&!$.configured);return{fields:N,aliases:U,missingSecrets:Q}}function A_(O){return O!==void 0&&O!==null&&O!==""}import{Box as x,Button as OP,HStack as G_,Muted as EO,Small as T,Text as NO,VStack as u}from"@contractspec/lib.design-system";import{jsx as k,jsxs as h}from"react/jsx-runtime";function wO({mode:O=e.selectedMode,onModeChange:K}){let{fields:_,aliases:P,missingSecrets:A}=N_(O);return k(x,{className:"rounded-2xl border border-border bg-card p-4",children:h(u,{gap:"lg",align:"stretch",children:[h(u,{gap:"xs",align:"stretch",children:[k(T,{className:"font-semibold uppercase tracking-wide",children:"BYOK and monorepo env setup"}),k(NO,{className:"text-muted-foreground text-sm",children:"The Integration Hub sample now publishes credential manifests, server-only secret references, and Next/Expo public aliases for multi-app workspaces."})]}),k(G_,{className:"flex-wrap gap-2",children:["managed","byok"].map((N)=>k(OP,{type:"button",variant:O===N?"default":"outline",onClick:()=>K?.(N),children:N==="byok"?"BYOK":"Managed"},N))}),h(u,{gap:"sm",align:"stretch",children:[k(T,{children:"Required setup fields"}),k(x,{className:"grid gap-2 md:grid-cols-2",children:_.map((N)=>k(x,{className:"rounded-xl border border-border bg-background p-3",children:h(G_,{className:"items-start justify-between gap-3",children:[h(u,{gap:"xs",align:"stretch",children:[k(NO,{className:"font-medium text-sm",children:q_(N.key)}),k(EO,{className:"text-xs",children:N.description}),N.secretRef?k(T,{className:"font-mono",children:N.secretRef}):null]}),k(T,{className:"rounded-full bg-muted px-2 py-0.5",children:N.configured?"configured":"missing"})]})},`${N.kind}:${N.key}`))})]}),h(u,{gap:"sm",align:"stretch",children:[k(T,{children:"App aliases"}),k(x,{className:"grid gap-2 md:grid-cols-2",children:P.map((N)=>h(x,{className:"rounded-xl border border-border bg-background p-3",children:[k(NO,{className:"font-mono text-sm",children:N.name}),h(EO,{className:"text-xs",children:[N.targetLabel," \xB7 ",N.framework," \xB7"," ",N.exposure??"server"]}),_P(N.name)?k(T,{className:"text-amber-600",children:"Public client alias"}):null]},`${N.targetId}:${N.name}`))})]}),A.length?h(x,{className:"rounded-xl border border-amber-300 bg-amber-50 p-3 text-amber-900 dark:border-amber-900 dark:bg-amber-950/30 dark:text-amber-100",children:[h(NO,{className:"font-medium text-sm",children:["Missing BYOK secret refs:"," ",A.map((N)=>q_(N.key)).join(", "),"."]}),k(EO,{className:"text-xs",children:"Secret fields stay server-only and are not materialized as NEXT_PUBLIC_* or EXPO_PUBLIC_* aliases."})]}):null]})})}function _P(O){return O.startsWith("NEXT_PUBLIC_")||O.startsWith("EXPO_PUBLIC_")}function q_(O){return O.replace(/[_-]+/g," ").replace(/\b\w/g,(K)=>K.toUpperCase())}import{Button as GO}from"@contractspec/lib.design-system";import{Badge as H_}from"@contractspec/lib.ui-kit-web/ui/badge";import{HStack as PP}from"@contractspec/lib.ui-kit-web/ui/stack";import{jsx as g,jsxs as AP}from"react/jsx-runtime";var KP={ACTIVE:"default",CONNECTED:"default",SUCCESS:"default",PENDING:"secondary",PAUSED:"secondary",ERROR:"destructive",DISCONNECTED:"outline"};function r(O){return O?O.toLocaleString():"Never"}function jO(O){return O?JSON.stringify(O,null,2):"No configuration"}function qO({status:O}){return g(H_,{variant:KP[O]??"outline",children:O})}function HO({controller:O,label:K,toggleColumnId:_,toggleVisibleLabel:P,toggleHiddenLabel:A,pinColumnId:N,pinLabel:U,resizeColumnId:Q,resizeLabel:$}){let B=O.rows[0],W=O.columns.find((G)=>G.id===_),H=O.columns.find((G)=>G.id===N),J=O.columns.find((G)=>G.id===Q),v=H?.pinState==="left"?!1:"left";return AP(PP,{gap:"sm",className:"flex-wrap",children:[g(H_,{variant:"outline",children:K}),g(GO,{variant:"outline",size:"sm",onPress:()=>B?.toggleExpanded?.(!B?.isExpanded),children:"Expand First Row"}),g(GO,{variant:"outline",size:"sm",onPress:()=>W?.toggleVisibility?.(!W?.visible),children:W?.visible?P:A}),g(GO,{variant:"outline",size:"sm",onPress:()=>H?.pin?.(v),children:H?.pinState==="left"?`Unpin ${U}`:`Pin ${U}`}),g(GO,{variant:"outline",size:"sm",onPress:()=>J?.resizeBy?.(40),children:$})]})}import{DataTable as NP}from"@contractspec/lib.design-system";import{useContractTable as GP}from"@contractspec/lib.presentation-runtime-react";import{VStack as U_}from"@contractspec/lib.ui-kit-web/ui/stack";import{Text as l}from"@contractspec/lib.ui-kit-web/ui/text";import{jsx as f,jsxs as xO}from"react/jsx-runtime";function TO({connections:O}){let K=GP({data:O,columns:[{id:"connection",header:"Connection",label:"Connection",accessor:(_)=>_.name,cell:({item:_})=>xO(U_,{gap:"xs",children:[f(l,{className:"font-medium text-sm",children:_.name}),xO(l,{className:"text-muted-foreground text-xs",children:["Created ",_.createdAt.toLocaleDateString()]})]}),size:240,minSize:180,canSort:!0,canPin:!0,canResize:!0},{id:"status",header:"Status",label:"Status",accessorKey:"status",cell:({value:_})=>f(qO,{status:String(_)}),size:150,canSort:!0,canPin:!0,canResize:!0},{id:"lastSyncAt",header:"Last Sync",label:"Last Sync",accessor:(_)=>_.lastSyncAt?.getTime()??0,cell:({item:_})=>r(_.lastSyncAt),size:200,canSort:!0,canHide:!0,canResize:!0},{id:"errorMessage",header:"Errors",label:"Errors",accessor:(_)=>_.errorMessage??"",cell:({value:_})=>String(_||"No errors"),size:240,canHide:!0,canResize:!0}],initialState:{pagination:{pageIndex:0,pageSize:3},columnVisibility:{errorMessage:!1},columnPinning:{left:["connection"],right:[]}},renderExpandedContent:(_)=>xO(U_,{gap:"sm",className:"py-2",children:[f(l,{className:"font-medium text-sm",children:"Credentials"}),f("pre",{className:"overflow-auto rounded-md bg-muted/40 p-3 text-xs",children:jO(_.credentials)}),f(l,{className:"font-medium text-sm",children:"Config"}),f("pre",{className:"overflow-auto rounded-md bg-muted/40 p-3 text-xs",children:jO(_.config)}),f(l,{className:"text-muted-foreground text-sm",children:_.errorMessage??"No sync errors recorded."})]}),getCanExpand:()=>!0});return f(NP,{controller:K,title:"Connections",description:"Client-mode ContractSpec table with visibility, pinning, resizing, and expanded diagnostics.",toolbar:f(HO,{controller:K,label:`${O.length} total connections`,toggleColumnId:"errorMessage",toggleVisibleLabel:"Hide Error Column",toggleHiddenLabel:"Show Error Column",pinColumnId:"status",pinLabel:"Status",resizeColumnId:"connection",resizeLabel:"Widen Connection"}),emptyState:f("div",{className:"rounded-md border border-dashed p-8 text-center text-muted-foreground text-sm",children:"No connections found"})})}import{DataTable as qP}from"@contractspec/lib.design-system";import{useContractTable as HP}from"@contractspec/lib.presentation-runtime-react";import{VStack as Y_}from"@contractspec/lib.ui-kit-web/ui/stack";import{Text as S}from"@contractspec/lib.ui-kit-web/ui/text";import{jsx as c,jsxs as w}from"react/jsx-runtime";function gO({syncConfigs:O}){let K=HP({data:O,columns:[{id:"sync",header:"Sync Config",label:"Sync Config",accessor:(_)=>_.name,cell:({item:_})=>w(Y_,{gap:"xs",children:[c(S,{className:"font-medium text-sm",children:_.name}),w(S,{className:"text-muted-foreground text-xs",children:[_.sourceEntity," \u2192 ",_.targetEntity]})]}),size:260,minSize:200,canSort:!0,canPin:!0,canResize:!0},{id:"frequency",header:"Frequency",label:"Frequency",accessorKey:"frequency",size:160,canSort:!0,canHide:!0,canResize:!0},{id:"status",header:"Status",label:"Status",accessorKey:"status",cell:({value:_})=>c(qO,{status:String(_)}),size:150,canSort:!0,canPin:!0,canResize:!0},{id:"recordsSynced",header:"Records",label:"Records",accessorKey:"recordsSynced",align:"right",size:140,canSort:!0,canResize:!0},{id:"lastRunAt",header:"Last Run",label:"Last Run",accessor:(_)=>_.lastRunAt?.getTime()??0,cell:({item:_})=>r(_.lastRunAt),size:200,canSort:!0,canHide:!0,canResize:!0}],initialState:{pagination:{pageIndex:0,pageSize:3},columnVisibility:{lastRunAt:!1},columnPinning:{left:["sync"],right:[]}},renderExpandedContent:(_)=>w(Y_,{gap:"sm",className:"py-2",children:[w(S,{className:"text-muted-foreground text-sm",children:["Connection ",_.connectionId]}),w(S,{className:"text-muted-foreground text-sm",children:["Last run: ",r(_.lastRunAt)]}),w(S,{className:"text-muted-foreground text-sm",children:["Last status: ",_.lastRunStatus??"No runs recorded"]}),w(S,{className:"text-muted-foreground text-sm",children:["Updated ",_.updatedAt.toLocaleString()]})]}),getCanExpand:()=>!0});return c(qP,{controller:K,title:"Sync Configs",description:"Shared table primitives applied to sync monitoring without changing the surrounding dashboard layout.",toolbar:c(HO,{controller:K,label:`${O.length} syncs`,toggleColumnId:"lastRunAt",toggleVisibleLabel:"Hide Last Run",toggleHiddenLabel:"Show Last Run",pinColumnId:"status",pinLabel:"Status",resizeColumnId:"sync",resizeLabel:"Widen Sync"}),emptyState:c("div",{className:"rounded-md border border-dashed p-8 text-center text-muted-foreground text-sm",children:"No sync configurations found"})})}import{Box as o,Button as X_,ErrorState as UP,HStack as UO,LoaderBlock as YP,StatCard as SO,StatCardGroup as XP,Text as M,VStack as B_}from"@contractspec/lib.design-system";import{useState as W_}from"react";import{jsx as D,jsxs as C}from"react/jsx-runtime";var BP={ACTIVE:"bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",INACTIVE:"bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400",CONNECTED:"bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",DISCONNECTED:"bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400",PENDING:"bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400",ERROR:"bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",PAUSED:"bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400"},WP={CRM:"\uD83D\uDCCA",MARKETING:"\uD83D\uDCE3",PAYMENT:"\uD83D\uDCB3",COMMUNICATION:"\uD83D\uDCAC",DATA:"\uD83D\uDDC4\uFE0F",CUSTOM:"\u2699\uFE0F"};function ZP(){let[O,K]=W_("integrations"),[_,P]=W_("byok"),{integrations:A,connections:N,syncConfigs:U,loading:Q,error:$,stats:B,refetch:W}=MO(),H=[{id:"integrations",label:"Integrations",icon:"\uD83D\uDD0C"},{id:"credentials",label:"BYOK/env",icon:"\uD83D\uDD10"},{id:"connections",label:"Connections",icon:"\uD83D\uDD17"},{id:"syncs",label:"Sync Configs",icon:"\uD83D\uDD04"},{id:"chat",label:"Chat",icon:"\uD83D\uDCAC"}];if(Q)return D(YP,{label:"Loading Integrations..."});if($)return D(UP,{title:"Failed to load Integrations",description:$.message,onRetry:W,retryLabel:"Retry"});return C(B_,{gap:"lg",align:"stretch",children:[C(UO,{className:"items-center justify-between",children:[D(M,{className:"font-bold text-2xl",children:"Integration Hub"}),D(X_,{onClick:()=>alert("Add integration modal"),children:C(UO,{className:"items-center gap-2",children:[D(M,{"aria-hidden":"true",children:"+"}),D(M,{children:"Add Integration"})]})})]}),C(XP,{children:[D(SO,{label:"Integrations",value:B.totalIntegrations,hint:`${B.activeIntegrations} active`}),D(SO,{label:"Connections",value:B.totalConnections,hint:`${B.connectedCount} connected`}),D(SO,{label:"Syncs",value:B.totalSyncs,hint:`${B.activeSyncs} active`})]}),D(P_,{connections:N,integrations:A,syncConfigs:U}),D(o,{className:"flex gap-1 rounded-lg bg-muted p-1",role:"tablist",children:H.map((J)=>C(X_,{type:"button",role:"tab","aria-selected":O===J.id,onClick:()=>K(J.id),className:`flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 font-medium text-sm transition-colors ${O===J.id?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"}`,children:[D(M,{"aria-hidden":"true",children:J.icon}),D(M,{children:J.label})]},J.id))}),C(o,{className:"min-h-[400px]",role:"tabpanel",children:[O==="integrations"&&C(o,{className:"grid gap-4 sm:grid-cols-2 lg:grid-cols-3",children:[A.map((J)=>C(o,{className:"cursor-pointer rounded-lg border border-border bg-card p-4 transition-colors hover:bg-muted/50",children:[C(UO,{className:"mb-3 items-center gap-3",children:[D(M,{className:"text-2xl",children:WP[J.type]??"\u2699\uFE0F"}),C(B_,{gap:"xs",align:"stretch",children:[D(M,{className:"font-medium",children:J.name}),D(M,{className:"text-muted-foreground text-sm",children:J.type})]})]}),C(UO,{className:"items-center justify-between",children:[D(M,{className:`inline-flex rounded-full px-2 py-0.5 font-medium text-xs ${BP[J.status]??""}`,children:J.status}),D(M,{className:"text-muted-foreground text-xs",children:J.createdAt.toLocaleDateString()})]})]},J.id)),A.length===0&&D(o,{className:"col-span-full flex h-64 items-center justify-center",children:D(M,{className:"text-muted-foreground",children:"No integrations configured"})})]}),O==="credentials"&&D(wO,{mode:_,onModeChange:P}),O==="connections"&&D(TO,{connections:N}),O==="chat"&&D(bO,{proxyUrl:"/api/chat",thinkingLevel:"thinking",suggestions:["List my integrations","Show sync status","Add a connection"],className:"min-h-[400px]"}),O==="syncs"&&D(gO,{syncConfigs:U})]})]})}var Z_=[{id:"int-1",name:"Salesforce",type:"CRM",status:"ACTIVE",connectionCount:3},{id:"int-2",name:"HubSpot",type:"MARKETING",status:"ACTIVE",connectionCount:2},{id:"int-3",name:"Stripe",type:"PAYMENT",status:"ACTIVE",connectionCount:1},{id:"int-4",name:"Slack",type:"COMMUNICATION",status:"INACTIVE",connectionCount:0},{id:"int-5",name:"Google Sheets",type:"DATA",status:"ACTIVE",connectionCount:5},{id:"int-6",name:"PostHog",type:"ANALYTICS",status:"ACTIVE",connectionCount:1}],yO=[{id:"conn-1",integrationId:"int-1",name:"Production Salesforce",status:"CONNECTED",lastSyncAt:"2024-01-16T10:00:00Z"},{id:"conn-2",integrationId:"int-1",name:"Sandbox Salesforce",status:"CONNECTED",lastSyncAt:"2024-01-15T14:00:00Z"},{id:"conn-3",integrationId:"int-2",name:"Marketing HubSpot",status:"CONNECTED",lastSyncAt:"2024-01-16T08:00:00Z"},{id:"conn-4",integrationId:"int-3",name:"Stripe Live",status:"CONNECTED",lastSyncAt:"2024-01-16T12:00:00Z"},{id:"conn-5",integrationId:"int-5",name:"Analytics Sheet",status:"ERROR",lastSyncAt:"2024-01-14T09:00:00Z",error:"Authentication expired"},{id:"conn-6",integrationId:"int-6",name:"PostHog Workspace",status:"CONNECTED",lastSyncAt:"2024-01-16T11:45:00Z"}],$_=[{id:"sync-1",connectionId:"conn-1",name:"Contacts Sync",frequency:"HOURLY",lastRunAt:"2024-01-16T10:00:00Z",status:"SUCCESS",recordsSynced:1250},{id:"sync-2",connectionId:"conn-1",name:"Opportunities Sync",frequency:"DAILY",lastRunAt:"2024-01-16T00:00:00Z",status:"SUCCESS",recordsSynced:340},{id:"sync-3",connectionId:"conn-3",name:"Orders Sync",frequency:"REALTIME",lastRunAt:"2024-01-16T12:30:00Z",status:"SUCCESS",recordsSynced:89},{id:"sync-4",connectionId:"conn-5",name:"Metrics Export",frequency:"DAILY",lastRunAt:"2024-01-14T09:00:00Z",status:"FAILED",recordsSynced:0}],$P={target:"markdown",render:async(O)=>{if(O.source.type!=="component"||O.source.componentKey!=="IntegrationDashboard")throw Error("integrationDashboardMarkdownRenderer: not IntegrationDashboard");let K=Z_,_=yO,P=$_,A=AO(K,_,P),N=K.filter((H)=>H.status==="ACTIVE"),U=_.filter((H)=>H.status==="CONNECTED"),Q=_.filter((H)=>H.status==="ERROR"),B=P.filter((H)=>H.status==="SUCCESS").reduce((H,J)=>H+J.recordsSynced,0),W=["# Integration Hub","","> Connect and sync data with external services","","## Overview","","| Metric | Value |","|--------|-------|",`| Active Integrations | ${N.length} |`,`| Connected Services | ${U.length} |`,`| Error Connections | ${Q.length} |`,`| Sync Configs | ${P.length} |`,`| Records Synced (24h) | ${B.toLocaleString()} |`,""];W.push("## Visualization Overview"),W.push("");for(let H of[...A.primaryItems,...A.comparisonItems])W.push(`- **${H.title}** via \`${H.spec.meta.key}\``);W.push(""),W.push("## Integrations"),W.push(""),W.push("| Name | Type | Connections | Status |"),W.push("|------|------|-------------|--------|");for(let H of K){let J=H.status==="ACTIVE"?"\uD83D\uDFE2":"\u26AB";W.push(`| ${H.name} | ${H.type} | ${H.connectionCount} | ${J} ${H.status} |`)}W.push(""),W.push("## Recent Sync Activity"),W.push(""),W.push("| Sync | Frequency | Last Run | Records | Status |"),W.push("|------|-----------|----------|---------|--------|");for(let H of P){let J=new Date(H.lastRunAt).toLocaleString(),v=H.status==="SUCCESS"?"\u2705":"\u274C";W.push(`| ${H.name} | ${H.frequency} | ${J} | ${H.recordsSynced} | ${v} ${H.status} |`)}if(Q.length>0){W.push(""),W.push("## \u26A0\uFE0F Connections with Errors"),W.push("");for(let H of Q){let J=K.find((v)=>v.id===H.integrationId);W.push(`- **${H.name}** (${J?.name??"Unknown"}): ${H.error??"Unknown error"}`)}}return{mimeType:"text/markdown",body:W.join(`
7
+ `)}}},JP={target:"markdown",render:async(O)=>{if(O.source.type!=="component"||O.source.componentKey!=="ConnectionList")throw Error("connectionListMarkdownRenderer: not ConnectionList");let K=yO,_=Z_,P=["# Connections","","> Manage connections to external services",""];for(let A of _){let N=K.filter((U)=>U.integrationId===A.id);if(N.length===0)continue;P.push(`## ${A.name}`),P.push(""),P.push("| Connection | Status | Last Sync |"),P.push("|------------|--------|-----------|");for(let U of N){let Q=new Date(U.lastSyncAt).toLocaleString(),$=U.status==="CONNECTED"?"\uD83D\uDFE2":U.status==="ERROR"?"\uD83D\uDD34":"\u26AB";P.push(`| ${U.name} | ${$} ${U.status} | ${Q} |`)}P.push("")}return{mimeType:"text/markdown",body:P.join(`
8
+ `)}}},QP={target:"markdown",render:async(O)=>{if(O.source.type!=="component"||O.source.componentKey!=="SyncConfigEditor")throw Error("syncConfigMarkdownRenderer: not SyncConfigEditor");let K=$_,_=yO,P=["# Sync Configurations","","> Configure automated data synchronization",""];for(let A of K){let N=_.find((Q)=>Q.id===A.connectionId),U=A.status==="SUCCESS"?"\u2705":"\u274C";P.push(`## ${A.name}`),P.push(""),P.push(`**Connection:** ${N?.name??"Unknown"}`),P.push(`**Frequency:** ${A.frequency}`),P.push(`**Status:** ${U} ${A.status}`),P.push(`**Last Run:** ${new Date(A.lastRunAt).toLocaleString()}`),P.push(`**Records Synced:** ${A.recordsSynced.toLocaleString()}`),P.push("")}return P.push("## Frequency Options"),P.push(""),P.push("- **REALTIME**: Sync on every change"),P.push("- **HOURLY**: Sync every hour"),P.push("- **DAILY**: Sync once per day"),P.push("- **WEEKLY**: Sync once per week"),P.push("- **MANUAL**: Sync only when triggered"),{mimeType:"text/markdown",body:P.join(`
9
+ `)}}};export{MO as useIntegrationData,QP as syncConfigMarkdownRenderer,sP as runIntegrationHubMcpExampleFromEnv,sO as integrationHubEnvironmentConfig,e as integrationHubCredentialSetupState,tO as integrationHubCredentialManifest,$P as integrationDashboardMarkdownRenderer,$K as hasChanges,WK as createSyncEngine,AO as createIntegrationVisualizationSections,z_ as createIntegrationHandlers,JP as connectionListMarkdownRenderer,ZK as computeChecksum,RO as TriggerSyncInputModel,y_ as TriggerSyncContract,a as SyncStatusEnum,d as SyncRunModel,j as SyncDirectionEnum,OO as SyncConfigModel,n as MappingTypeEnum,IO as ListSyncRunsOutputModel,zO as ListSyncRunsInputModel,d_ as ListSyncRunsContract,O_ as IntegrationVisualizationSpecs,zK as IntegrationVisualizationRegistry,IK as IntegrationVisualizationRefs,CO as IntegrationTypeVisualization,QO as IntegrationStatusEnum,s as IntegrationModel,wO as IntegrationHubCredentialSetupPreview,bO as IntegrationHubChat,ZP as IntegrationDashboard,fO as HealthySyncMetricVisualization,y as FieldMappingModel,F_ as ExamplesIntegrationHubExample,kO as CreateSyncConfigInputModel,g_ as CreateSyncConfigContract,DO as CreateIntegrationInputModel,M_ as CreateIntegrationContract,ZO as CreateConnectionInputModel,L_ as CreateConnectionContract,hO as ConnectionStatusVisualization,XO as ConnectionStatusEnum,i as ConnectionModel,aO as BasicSyncEngine,eO as BasicFieldTransformer,vO as AttentionSyncMetricVisualization,FO as AddFieldMappingInputModel,S_ as AddFieldMappingContract};
@@ -15,7 +15,7 @@ import{registerDocBlocks as m}from"@contractspec/lib.contracts-spec/docs";var f=
15
15
 
16
16
  ## UI / Presentations
17
17
 
18
- - Dashboard, integration list, connection detail, sync config editor, and shared ContractSpec tables for connections/sync configs.
18
+ - Dashboard, integration list, connection detail, sync config editor, BYOK/env setup preview, and shared ContractSpec tables for connections/sync configs.
19
19
  - Templates registered as \`integration-hub\` in Template Registry.
20
20
 
21
21
  ## Notes
@@ -23,6 +23,7 @@ import{registerDocBlocks as m}from"@contractspec/lib.contracts-spec/docs";var f=
23
23
  - Providers remain agnostic; keep mappings declarative for safe regeneration.
24
24
  - Seed data includes voice integrations for \`ai-voice.gradium\` and \`ai-voice.fal\`.
25
25
  - Feature flags can gate specific providers; metering can track sync volume.
26
+ - \`src/setup/credential-setup.ts\` demonstrates managed/BYOK credential manifests, secret references, and app-specific \`NEXT_PUBLIC_*\` / \`EXPO_PUBLIC_*\` aliases.
26
27
  - The dashboard tables demonstrate client-mode sorting, pagination, visibility, pinning, resizing, and row expansion on the shared table stack.
27
28
  `},{id:"docs.examples.integration-hub.goal",title:"Integration Hub — Goal",summary:"Why this integration hub exists and what success looks like.",kind:"goal",visibility:"public",route:"/docs/examples/integration-hub/goal",tags:["integrations","goal"],body:`## Why it matters
28
29
  - Gives a regenerable, provider-agnostic integration hub with explicit mappings.
@@ -37,7 +38,8 @@ import{registerDocBlocks as m}from"@contractspec/lib.contracts-spec/docs";var f=
37
38
  - Sync events and logs provide auditability; payloads are stored and PII-scoped.`},{id:"docs.examples.integration-hub.usage",title:"Integration Hub — Usage",summary:"How to configure connectors, mappings, and scheduled syncs.",kind:"usage",visibility:"public",route:"/docs/examples/integration-hub/usage",tags:["integrations","usage"],body:`## Setup
38
39
  1) Seed integrations/connections (if available) or create connector definitions.
39
40
  2) Configure sync jobs with Jobs module; store payload archives via Files.
40
- 3) Use \`src/run-mcp.ts\` to validate MCP connectivity for provider adapters.
41
+ 3) Use \`src/setup/credential-setup.ts\` to map managed/BYOK fields to per-app env aliases.
42
+ 4) Use \`src/run-mcp.ts\` to validate MCP connectivity for provider adapters.
41
43
 
42
44
  ## Extend & regenerate
43
45
  1) Add mapping fields or provider configs in the spec; include validation and PII paths.
@@ -55,6 +57,7 @@ import{registerDocBlocks as m}from"@contractspec/lib.contracts-spec/docs";var f=
55
57
  ## PII & Payloads
56
58
  - Treat payload archives as potentially sensitive; mark policy.pii paths.
57
59
  - For MCP/web, avoid exposing raw credentials/tokens; store via provider adapters only.
60
+ - Secret fields must not be materialized through public aliases such as \`NEXT_PUBLIC_*\` or \`EXPO_PUBLIC_*\`.
58
61
  - Keep MCP endpoint URLs, headers, and tokens in provider connection config, never in mappings.
59
62
 
60
63
  ## Verification