@enfyra/mcp-server 0.1.69 → 0.1.71

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 (248) hide show
  1. package/README.md +1 -1
  2. package/dist/lib/config-local-adapters.d.ts +18 -0
  3. package/dist/lib/config-local-adapters.js +271 -0
  4. package/dist/lib/config-local-adapters.js.map +1 -0
  5. package/dist/lib/config-local-contracts.d.ts +28 -0
  6. package/dist/lib/config-local-contracts.js +200 -0
  7. package/dist/lib/config-local-contracts.js.map +1 -0
  8. package/dist/lib/config-local-prompts.d.ts +10 -0
  9. package/dist/lib/config-local-prompts.js +185 -0
  10. package/dist/lib/config-local-prompts.js.map +1 -0
  11. package/dist/lib/config-local-types.d.ts +23 -0
  12. package/dist/lib/config-local-types.js +2 -0
  13. package/dist/lib/config-local-types.js.map +1 -0
  14. package/dist/lib/config-local.js +3 -649
  15. package/dist/lib/config-local.js.map +1 -1
  16. package/dist/lib/discovery-tools.d.ts +4 -0
  17. package/dist/lib/discovery-tools.js +546 -0
  18. package/dist/lib/discovery-tools.js.map +1 -0
  19. package/dist/lib/dynamic-repository-builder.d.ts +1 -1
  20. package/dist/lib/dynamic-script-context-contract.d.ts +100 -0
  21. package/dist/lib/dynamic-script-context-contract.js +163 -0
  22. package/dist/lib/dynamic-script-context-contract.js.map +1 -0
  23. package/dist/lib/enfyra-mcp-server.d.ts +3 -0
  24. package/dist/lib/enfyra-mcp-server.js +79 -0
  25. package/dist/lib/enfyra-mcp-server.js.map +1 -0
  26. package/dist/lib/enfyra-tool-logic.d.ts +7 -0
  27. package/dist/lib/enfyra-tool-logic.js +8 -0
  28. package/dist/lib/enfyra-tool-logic.js.map +1 -0
  29. package/dist/lib/enfyra-tool-types.d.ts +27 -0
  30. package/dist/lib/enfyra-tool-types.js +2 -0
  31. package/dist/lib/enfyra-tool-types.js.map +1 -0
  32. package/dist/lib/extension-api-builders.d.ts +17 -0
  33. package/dist/lib/extension-api-builders.js +235 -0
  34. package/dist/lib/extension-api-builders.js.map +1 -0
  35. package/dist/lib/extension-component-builders.d.ts +87 -0
  36. package/dist/lib/extension-component-builders.js +623 -0
  37. package/dist/lib/extension-component-builders.js.map +1 -0
  38. package/dist/lib/extension-contract-review.d.ts +26 -0
  39. package/dist/lib/extension-contract-review.js +187 -0
  40. package/dist/lib/extension-contract-review.js.map +1 -0
  41. package/dist/lib/extension-theme-contract.d.ts +63 -0
  42. package/dist/lib/extension-theme-contract.js +417 -0
  43. package/dist/lib/extension-theme-contract.js.map +1 -0
  44. package/dist/lib/identity-tools.d.ts +4 -0
  45. package/dist/lib/identity-tools.js +46 -0
  46. package/dist/lib/identity-tools.js.map +1 -0
  47. package/dist/lib/log-tools.d.ts +4 -0
  48. package/dist/lib/log-tools.js +65 -0
  49. package/dist/lib/log-tools.js.map +1 -0
  50. package/dist/lib/mcp-example-connect.d.ts +9 -0
  51. package/dist/lib/mcp-example-connect.js +442 -0
  52. package/dist/lib/mcp-example-connect.js.map +1 -0
  53. package/dist/lib/mcp-example-extensions.d.ts +9 -0
  54. package/dist/lib/mcp-example-extensions.js +729 -0
  55. package/dist/lib/mcp-example-extensions.js.map +1 -0
  56. package/dist/lib/mcp-example-files.d.ts +9 -0
  57. package/dist/lib/mcp-example-files.js +51 -0
  58. package/dist/lib/mcp-example-files.js.map +1 -0
  59. package/dist/lib/mcp-example-flows.d.ts +9 -0
  60. package/dist/lib/mcp-example-flows.js +76 -0
  61. package/dist/lib/mcp-example-flows.js.map +1 -0
  62. package/dist/lib/mcp-example-graphql.d.ts +9 -0
  63. package/dist/lib/mcp-example-graphql.js +57 -0
  64. package/dist/lib/mcp-example-graphql.js.map +1 -0
  65. package/dist/lib/mcp-example-handlers-hooks.d.ts +9 -0
  66. package/dist/lib/mcp-example-handlers-hooks.js +328 -0
  67. package/dist/lib/mcp-example-handlers-hooks.js.map +1 -0
  68. package/dist/lib/mcp-example-oauth-setup.d.ts +9 -0
  69. package/dist/lib/mcp-example-oauth-setup.js +41 -0
  70. package/dist/lib/mcp-example-oauth-setup.js.map +1 -0
  71. package/dist/lib/mcp-example-permissions-rls.d.ts +9 -0
  72. package/dist/lib/mcp-example-permissions-rls.js +210 -0
  73. package/dist/lib/mcp-example-permissions-rls.js.map +1 -0
  74. package/dist/lib/mcp-example-queries-deep.d.ts +9 -0
  75. package/dist/lib/mcp-example-queries-deep.js +220 -0
  76. package/dist/lib/mcp-example-queries-deep.js.map +1 -0
  77. package/dist/lib/mcp-example-schema-relations.d.ts +9 -0
  78. package/dist/lib/mcp-example-schema-relations.js +148 -0
  79. package/dist/lib/mcp-example-schema-relations.js.map +1 -0
  80. package/dist/lib/mcp-example-websocket.d.ts +9 -0
  81. package/dist/lib/mcp-example-websocket.js +103 -0
  82. package/dist/lib/mcp-example-websocket.js.map +1 -0
  83. package/dist/lib/mcp-examples.d.ts +5 -5
  84. package/dist/lib/mcp-examples.js +22 -2394
  85. package/dist/lib/mcp-examples.js.map +1 -1
  86. package/dist/lib/method-tools.d.ts +4 -0
  87. package/dist/lib/method-tools.js +217 -0
  88. package/dist/lib/method-tools.js.map +1 -0
  89. package/dist/lib/package-tools.d.ts +4 -0
  90. package/dist/lib/package-tools.js +98 -0
  91. package/dist/lib/package-tools.js.map +1 -0
  92. package/dist/lib/platform-data-operations.d.ts +24 -0
  93. package/dist/lib/platform-data-operations.js +71 -0
  94. package/dist/lib/platform-data-operations.js.map +1 -0
  95. package/dist/lib/platform-endpoint-workflow.d.ts +42 -0
  96. package/dist/lib/platform-endpoint-workflow.js +382 -0
  97. package/dist/lib/platform-endpoint-workflow.js.map +1 -0
  98. package/dist/lib/platform-extension-source.d.ts +487 -0
  99. package/dist/lib/platform-extension-source.js +524 -0
  100. package/dist/lib/platform-extension-source.js.map +1 -0
  101. package/dist/lib/platform-extension-tools.d.ts +1 -0
  102. package/dist/lib/platform-extension-tools.js +416 -0
  103. package/dist/lib/platform-extension-tools.js.map +1 -0
  104. package/dist/lib/platform-extension-ui.d.ts +4 -0
  105. package/dist/lib/platform-extension-ui.js +5 -0
  106. package/dist/lib/platform-extension-ui.js.map +1 -0
  107. package/dist/lib/platform-extension-workflow.d.ts +54 -0
  108. package/dist/lib/platform-extension-workflow.js +194 -0
  109. package/dist/lib/platform-extension-workflow.js.map +1 -0
  110. package/dist/lib/platform-flow-operations.d.ts +554 -0
  111. package/dist/lib/platform-flow-operations.js +317 -0
  112. package/dist/lib/platform-flow-operations.js.map +1 -0
  113. package/dist/lib/platform-flow-tools.d.ts +1 -0
  114. package/dist/lib/platform-flow-tools.js +248 -0
  115. package/dist/lib/platform-flow-tools.js.map +1 -0
  116. package/dist/lib/platform-operation-logic.d.ts +10 -0
  117. package/dist/lib/platform-operation-logic.js +11 -0
  118. package/dist/lib/platform-operation-logic.js.map +1 -0
  119. package/dist/lib/platform-operation-tools.d.ts +1 -324
  120. package/dist/lib/platform-operation-tools.js +13 -4620
  121. package/dist/lib/platform-operation-tools.js.map +1 -1
  122. package/dist/lib/platform-operation-types.d.ts +46 -0
  123. package/dist/lib/platform-operation-types.js +2 -0
  124. package/dist/lib/platform-operation-types.js.map +1 -0
  125. package/dist/lib/platform-policy-tools.d.ts +1 -0
  126. package/dist/lib/platform-policy-tools.js +248 -0
  127. package/dist/lib/platform-policy-tools.js.map +1 -0
  128. package/dist/lib/platform-resource-operations.d.ts +124 -0
  129. package/dist/lib/platform-resource-operations.js +109 -0
  130. package/dist/lib/platform-resource-operations.js.map +1 -0
  131. package/dist/lib/platform-resource-tools.d.ts +1 -0
  132. package/dist/lib/platform-resource-tools.js +70 -0
  133. package/dist/lib/platform-resource-tools.js.map +1 -0
  134. package/dist/lib/platform-route-operations.d.ts +222 -0
  135. package/dist/lib/platform-route-operations.js +290 -0
  136. package/dist/lib/platform-route-operations.js.map +1 -0
  137. package/dist/lib/platform-route-tools.d.ts +1 -0
  138. package/dist/lib/platform-route-tools.js +307 -0
  139. package/dist/lib/platform-route-tools.js.map +1 -0
  140. package/dist/lib/platform-shared-operations.d.ts +7 -0
  141. package/dist/lib/platform-shared-operations.js +4 -0
  142. package/dist/lib/platform-shared-operations.js.map +1 -0
  143. package/dist/lib/platform-websocket-tools.d.ts +1 -0
  144. package/dist/lib/platform-websocket-tools.js +70 -0
  145. package/dist/lib/platform-websocket-tools.js.map +1 -0
  146. package/dist/lib/record-tools.d.ts +4 -0
  147. package/dist/lib/record-tools.js +418 -0
  148. package/dist/lib/record-tools.js.map +1 -0
  149. package/dist/lib/required-knowledge.d.ts +1 -1
  150. package/dist/lib/required-knowledge.js +3 -2
  151. package/dist/lib/required-knowledge.js.map +1 -1
  152. package/dist/lib/route-access-tools.d.ts +4 -0
  153. package/dist/lib/route-access-tools.js +172 -0
  154. package/dist/lib/route-access-tools.js.map +1 -0
  155. package/dist/lib/route-definition-tools.d.ts +4 -0
  156. package/dist/lib/route-definition-tools.js +285 -0
  157. package/dist/lib/route-definition-tools.js.map +1 -0
  158. package/dist/lib/route-inspection-tools.d.ts +4 -0
  159. package/dist/lib/route-inspection-tools.js +319 -0
  160. package/dist/lib/route-inspection-tools.js.map +1 -0
  161. package/dist/lib/route-tools.d.ts +1 -0
  162. package/dist/lib/route-tools.js +9 -0
  163. package/dist/lib/route-tools.js.map +1 -0
  164. package/dist/lib/runtime-zone-registry.d.ts +27 -0
  165. package/dist/lib/runtime-zone-registry.js +81 -0
  166. package/dist/lib/runtime-zone-registry.js.map +1 -0
  167. package/dist/lib/runtime-zone-search.d.ts +303 -0
  168. package/dist/lib/runtime-zone-search.js +596 -0
  169. package/dist/lib/runtime-zone-search.js.map +1 -0
  170. package/dist/lib/runtime-zone-tools.d.ts +2 -307
  171. package/dist/lib/runtime-zone-tools.js +2 -674
  172. package/dist/lib/runtime-zone-tools.js.map +1 -1
  173. package/dist/lib/schema-column-tools.d.ts +3 -0
  174. package/dist/lib/schema-column-tools.js +80 -0
  175. package/dist/lib/schema-column-tools.js.map +1 -0
  176. package/dist/lib/schema-mutation-coordinator.d.ts +28 -0
  177. package/dist/lib/schema-mutation-coordinator.js +154 -0
  178. package/dist/lib/schema-mutation-coordinator.js.map +1 -0
  179. package/dist/lib/schema-relation-contracts.d.ts +39 -0
  180. package/dist/lib/schema-relation-contracts.js +160 -0
  181. package/dist/lib/schema-relation-contracts.js.map +1 -0
  182. package/dist/lib/schema-relation-tools.d.ts +3 -0
  183. package/dist/lib/schema-relation-tools.js +61 -0
  184. package/dist/lib/schema-relation-tools.js.map +1 -0
  185. package/dist/lib/schema-table-contracts.d.ts +28 -0
  186. package/dist/lib/schema-table-contracts.js +263 -0
  187. package/dist/lib/schema-table-contracts.js.map +1 -0
  188. package/dist/lib/schema-table-tools.d.ts +3 -0
  189. package/dist/lib/schema-table-tools.js +297 -0
  190. package/dist/lib/schema-table-tools.js.map +1 -0
  191. package/dist/lib/schema-tool-operations.d.ts +150 -0
  192. package/dist/lib/schema-tool-operations.js +468 -0
  193. package/dist/lib/schema-tool-operations.js.map +1 -0
  194. package/dist/lib/schema-tool-types.d.ts +38 -0
  195. package/dist/lib/schema-tool-types.js +2 -0
  196. package/dist/lib/schema-tool-types.js.map +1 -0
  197. package/dist/lib/schema-verification.d.ts +14 -0
  198. package/dist/lib/schema-verification.js +105 -0
  199. package/dist/lib/schema-verification.js.map +1 -0
  200. package/dist/lib/script-tools.d.ts +4 -0
  201. package/dist/lib/script-tools.js +127 -0
  202. package/dist/lib/script-tools.js.map +1 -0
  203. package/dist/lib/system-tools.d.ts +4 -0
  204. package/dist/lib/system-tools.js +41 -0
  205. package/dist/lib/system-tools.js.map +1 -0
  206. package/dist/lib/table-tool-logic.d.ts +5 -0
  207. package/dist/lib/table-tool-logic.js +6 -0
  208. package/dist/lib/table-tool-logic.js.map +1 -0
  209. package/dist/lib/table-tools.d.ts +1 -84
  210. package/dist/lib/table-tools.js +7 -1522
  211. package/dist/lib/table-tools.js.map +1 -1
  212. package/dist/lib/tool-catalog.d.ts +2 -1
  213. package/dist/lib/tool-catalog.js +23 -2
  214. package/dist/lib/tool-catalog.js.map +1 -1
  215. package/dist/lib/tool-metadata-operations.d.ts +27 -0
  216. package/dist/lib/tool-metadata-operations.js +93 -0
  217. package/dist/lib/tool-metadata-operations.js.map +1 -0
  218. package/dist/lib/tool-permission-profile.d.ts +37 -0
  219. package/dist/lib/tool-permission-profile.js +106 -0
  220. package/dist/lib/tool-permission-profile.js.map +1 -0
  221. package/dist/lib/tool-record-operations.d.ts +102 -0
  222. package/dist/lib/tool-record-operations.js +260 -0
  223. package/dist/lib/tool-record-operations.js.map +1 -0
  224. package/dist/lib/tool-route-inspection.d.ts +47 -0
  225. package/dist/lib/tool-route-inspection.js +168 -0
  226. package/dist/lib/tool-route-inspection.js.map +1 -0
  227. package/dist/lib/tool-routing.d.ts +3 -417
  228. package/dist/lib/tool-routing.js +3 -1038
  229. package/dist/lib/tool-routing.js.map +1 -1
  230. package/dist/lib/tool-runtime-config.d.ts +33 -0
  231. package/dist/lib/tool-runtime-config.js +237 -0
  232. package/dist/lib/tool-runtime-config.js.map +1 -0
  233. package/dist/lib/tool-script-operations.d.ts +34 -0
  234. package/dist/lib/tool-script-operations.js +153 -0
  235. package/dist/lib/tool-script-operations.js.map +1 -0
  236. package/dist/lib/workflow-definitions.d.ts +366 -0
  237. package/dist/lib/workflow-definitions.js +703 -0
  238. package/dist/lib/workflow-definitions.js.map +1 -0
  239. package/dist/lib/workflow-planner.d.ts +45 -0
  240. package/dist/lib/workflow-planner.js +338 -0
  241. package/dist/lib/workflow-planner.js.map +1 -0
  242. package/dist/lib/workflow-types.d.ts +39 -0
  243. package/dist/lib/workflow-types.js +2 -0
  244. package/dist/lib/workflow-types.js.map +1 -0
  245. package/dist/mcp-server-entry.d.ts +0 -3
  246. package/dist/mcp-server-entry.js +2 -3249
  247. package/dist/mcp-server-entry.js.map +1 -1
  248. package/package.json +1 -1
@@ -0,0 +1,442 @@
1
+ export const connectExamples = {
2
+ title: 'Connect SSR and browser apps to Enfyra',
3
+ useWhen: 'Use when connecting Nuxt, Next, Angular, or another browser app to Enfyra for REST, login, OAuth, refresh, files, GraphQL, or Socket.IO; adapt the framework wrapper while preserving the app-origin proxy and cookie boundary.',
4
+ examples: [
5
+ {
6
+ name: 'Nuxt routeRules for REST and Socket.IO',
7
+ code: `export default defineNuxtConfig({
8
+ routeRules: {
9
+ "/enfyra/**": {
10
+ proxy: {
11
+ to: \`\${process.env.ENFYRA_API_URL}/**\`,
12
+ fetchOptions: { redirect: "manual" }
13
+ }
14
+ },
15
+ "/socket.io/**": {
16
+ proxy: \`\${process.env.ENFYRA_APP_URL}/ws/socket.io/**\`
17
+ }
18
+ }
19
+ })`,
20
+ notes: [
21
+ 'Browser code calls app-origin routes such as /enfyra/login, /enfyra/me, /enfyra/logout, and /enfyra/<table>.',
22
+ 'Keep redirects manual so OAuth and the set-cookie bridge return their redirect response to the browser.',
23
+ 'Proxy to the Enfyra app /api bridge, not the raw Enfyra server. The Enfyra app bridge reads and refreshes cookies, then injects Authorization for protected ESV requests.',
24
+ ],
25
+ },
26
+ {
27
+ name: 'Next rewrites for REST and Socket.IO',
28
+ code: `const nextConfig = {
29
+ async rewrites() {
30
+ return [
31
+ {
32
+ source: "/enfyra/:path*",
33
+ destination: \`\${process.env.ENFYRA_API_URL}/:path*\`
34
+ },
35
+ {
36
+ source: "/socket.io/",
37
+ destination: \`\${process.env.ENFYRA_APP_URL}/ws/socket.io/\`
38
+ }
39
+ ]
40
+ }
41
+ }
42
+
43
+ export default nextConfig`,
44
+ notes: [
45
+ 'Use rewrites for browser traffic, including the OAuth cookie bridge.',
46
+ 'The destination is the Enfyra app /api bridge. Do not point the browser rewrite at a raw ESV origin.',
47
+ 'For server components, forward the incoming Cookie header when fetching through the third app origin.',
48
+ ],
49
+ },
50
+ {
51
+ name: 'Angular dev proxy for REST and Socket.IO',
52
+ code: `// src/proxy.conf.json
53
+ {
54
+ "/enfyra/**": {
55
+ "target": "https://demo.enfyra.io/api",
56
+ "secure": true,
57
+ "changeOrigin": true,
58
+ "pathRewrite": {
59
+ "^/enfyra": ""
60
+ }
61
+ },
62
+ "/socket.io/**": {
63
+ "target": "https://demo.enfyra.io/api/ws",
64
+ "secure": true,
65
+ "changeOrigin": true,
66
+ "ws": true
67
+ }
68
+ }
69
+
70
+ // angular.json
71
+ {
72
+ "projects": {
73
+ "app": {
74
+ "architect": {
75
+ "serve": {
76
+ "options": {
77
+ "proxyConfig": "src/proxy.conf.json"
78
+ }
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }`,
84
+ notes: [
85
+ 'Browser code still calls /enfyra/login, /enfyra/me, /enfyra/logout, and /enfyra/<table>.',
86
+ 'The /enfyra proxy strips the prefix before forwarding to the Enfyra API origin.',
87
+ 'The /socket.io proxy forwards to the Enfyra app bridge /ws/socket.io while keeping the browser transport path as /socket.io.',
88
+ 'Restart ng serve after changing proxy.conf.json.',
89
+ ],
90
+ },
91
+ {
92
+ name: 'Password login and current user fetch',
93
+ code: `await fetch("/enfyra/login", {
94
+ method: "POST",
95
+ credentials: "include",
96
+ headers: { "Content-Type": "application/json" },
97
+ body: JSON.stringify({ email, password, remember: true })
98
+ })
99
+
100
+ const me = await fetch("/enfyra/me", {
101
+ credentials: "include"
102
+ }).then((res) => res.ok ? res.json() : null)`,
103
+ notes: [
104
+ 'The third app proxy maps /enfyra/login to the Enfyra app /api/login cookie endpoint; use /login, not raw /auth/login, in browser cookie mode.',
105
+ 'The Enfyra app bridge owns refresh and Bearer forwarding to ESV while HttpOnly cookies stay outside browser JavaScript.',
106
+ 'Do not read or store JWTs in browser JavaScript in proxy-cookie mode.',
107
+ ],
108
+ },
109
+ {
110
+ name: 'Nuxt client plugin for authenticated realtime',
111
+ code: `// composables/useRealtime.ts
112
+ import { io, type Socket } from "socket.io-client"
113
+ import { readonly, ref, shallowRef } from "vue"
114
+
115
+ const socket = shallowRef<Socket | null>(null)
116
+ const isConnected = ref(false)
117
+
118
+ export function useRealtime() {
119
+ function connect() {
120
+ if (import.meta.server) return null
121
+ if (socket.value) return socket.value
122
+
123
+ const nextSocket = io("/chat", {
124
+ path: "/socket.io",
125
+ withCredentials: true,
126
+ reconnection: true,
127
+ reconnectionAttempts: Infinity,
128
+ reconnectionDelay: 2000,
129
+ reconnectionDelayMax: 30000
130
+ })
131
+
132
+ nextSocket.on("connect", () => {
133
+ isConnected.value = true
134
+ })
135
+ nextSocket.on("disconnect", () => {
136
+ isConnected.value = false
137
+ })
138
+
139
+ socket.value = nextSocket
140
+ return nextSocket
141
+ }
142
+
143
+ function disconnect() {
144
+ if (!socket.value) return
145
+ socket.value.disconnect()
146
+ socket.value = null
147
+ isConnected.value = false
148
+ }
149
+
150
+ function onMessage(handler) {
151
+ const activeSocket = socket.value ?? connect()
152
+ if (!activeSocket) return () => {}
153
+ activeSocket.on("chat:message", handler)
154
+ return () => activeSocket.off("chat:message", handler)
155
+ }
156
+
157
+ return { socket, isConnected: readonly(isConnected), connect, disconnect, onMessage }
158
+ }
159
+
160
+ // plugins/realtime.client.ts
161
+ import { watch } from "vue"
162
+
163
+ export default defineNuxtPlugin(() => {
164
+ const { me } = useAuth()
165
+ const realtime = useRealtime()
166
+
167
+ watch(
168
+ me,
169
+ user => {
170
+ if (user) realtime.connect()
171
+ else realtime.disconnect()
172
+ },
173
+ { immediate: true }
174
+ )
175
+ })
176
+
177
+ // pages/chat.vue
178
+ const realtime = useRealtime()
179
+ let stopRealtime = () => {}
180
+
181
+ onMounted(() => {
182
+ stopRealtime = realtime.onMessage(event => {
183
+ // Update local UI state, then debounce REST refresh if full state is needed.
184
+ })
185
+ })
186
+
187
+ onUnmounted(() => {
188
+ stopRealtime()
189
+ })`,
190
+ notes: [
191
+ 'Create the socket once in a client-only plugin after auth has resolved; pages should not own the initial connection lifecycle.',
192
+ 'Use the websocket namespace path from live metadata, such as /chat, and keep the transport path as /socket.io.',
193
+ 'Proxy /socket.io/** to the Enfyra app bridge /ws/socket.io/** so cookies are same-origin.',
194
+ 'Route components add event listeners and remove them on unmount; they can optimistically update local state and debounce REST refreshes.',
195
+ 'Disconnect the singleton socket when the current user/session clears.',
196
+ ],
197
+ },
198
+ {
199
+ name: 'Angular HttpClient auth service and route guard',
200
+ code: `// app.config.ts
201
+ import { ApplicationConfig, inject } from "@angular/core"
202
+ import { provideRouter, CanActivateFn, Router } from "@angular/router"
203
+ import { HttpInterceptorFn, provideHttpClient, withInterceptors } from "@angular/common/http"
204
+ import { catchError, map, of } from "rxjs"
205
+
206
+ import { routes } from "./app.routes"
207
+ import { EnfyraAuthService } from "./enfyra-auth.service"
208
+
209
+ export const enfyraCredentialsInterceptor: HttpInterceptorFn = (req, next) => {
210
+ if (!req.url.startsWith("/enfyra/")) return next(req)
211
+ return next(req.clone({ withCredentials: true }))
212
+ }
213
+
214
+ export const requireUserGuard: CanActivateFn = () => {
215
+ const auth = inject(EnfyraAuthService)
216
+ const router = inject(Router)
217
+
218
+ return auth.loadMe().pipe(
219
+ map(user => user ? true : router.createUrlTree(["/login"])),
220
+ catchError(() => of(router.createUrlTree(["/login"])))
221
+ )
222
+ }
223
+
224
+ export const appConfig: ApplicationConfig = {
225
+ providers: [
226
+ provideHttpClient(withInterceptors([enfyraCredentialsInterceptor])),
227
+ provideRouter(routes)
228
+ ]
229
+ }
230
+
231
+ // enfyra-auth.service.ts
232
+ import { Injectable, signal } from "@angular/core"
233
+ import { HttpClient } from "@angular/common/http"
234
+ import { Observable, tap } from "rxjs"
235
+
236
+ type EnfyraUser = { id: string | number; email?: string }
237
+
238
+ @Injectable({ providedIn: "root" })
239
+ export class EnfyraAuthService {
240
+ readonly user = signal<EnfyraUser | null>(null)
241
+
242
+ constructor(private readonly http: HttpClient) {}
243
+
244
+ login(email: string, password: string): Observable<unknown> {
245
+ return this.http.post("/enfyra/login", { email, password, remember: true }).pipe(
246
+ tap(() => this.loadMe().subscribe())
247
+ )
248
+ }
249
+
250
+ loadMe(): Observable<EnfyraUser | null> {
251
+ return this.http.get<EnfyraUser | null>("/enfyra/me").pipe(
252
+ tap(user => this.user.set(user))
253
+ )
254
+ }
255
+
256
+ logout(): Observable<unknown> {
257
+ return this.http.post("/enfyra/logout", {}).pipe(
258
+ tap(() => this.user.set(null))
259
+ )
260
+ }
261
+
262
+ startGoogleOAuth(returnPath = "/") {
263
+ const redirect = new URL(returnPath, window.location.origin)
264
+ const url = new URL("/api/auth/google", "https://demo.enfyra.io")
265
+ url.searchParams.set("redirect", redirect.toString())
266
+ url.searchParams.set("cookieBridgePrefix", "/enfyra")
267
+ window.location.href = url.toString()
268
+ }
269
+ }`,
270
+ notes: [
271
+ 'Use HttpClient with a credentials interceptor for /enfyra/* calls so cookies are sent consistently.',
272
+ 'The guard is only for user experience; Enfyra route permissions and server-side owner checks remain authoritative.',
273
+ 'Keep the current user in an Angular service or store; do not read JWTs from cookies or URLs.',
274
+ 'OAuth starts at the Enfyra app /api/auth/google URL, not the local /enfyra path. It returns through the local cookie bridge before Angular loads /enfyra/me.',
275
+ ],
276
+ },
277
+ {
278
+ name: 'Next client provider for authenticated realtime',
279
+ code: `"use client"
280
+
281
+ // app/realtime-provider.tsx
282
+ import { createContext, useContext, useEffect, useMemo, useRef, useState } from "react"
283
+ import { io, type Socket } from "socket.io-client"
284
+
285
+ type RealtimeContextValue = {
286
+ socket: Socket | null
287
+ isConnected: boolean
288
+ }
289
+
290
+ const RealtimeContext = createContext<RealtimeContextValue>({
291
+ socket: null,
292
+ isConnected: false
293
+ })
294
+
295
+ export function RealtimeProvider({
296
+ user,
297
+ children
298
+ }: {
299
+ user: { id: string | number } | null
300
+ children: React.ReactNode
301
+ }) {
302
+ const socketRef = useRef<Socket | null>(null)
303
+ const [isConnected, setConnected] = useState(false)
304
+
305
+ useEffect(() => {
306
+ if (!user) {
307
+ socketRef.current?.disconnect()
308
+ socketRef.current = null
309
+ setConnected(false)
310
+ return
311
+ }
312
+
313
+ if (socketRef.current) return
314
+
315
+ const socket = io("/chat", {
316
+ path: "/socket.io",
317
+ withCredentials: true,
318
+ reconnection: true,
319
+ reconnectionAttempts: Infinity,
320
+ reconnectionDelay: 2000,
321
+ reconnectionDelayMax: 30000
322
+ })
323
+
324
+ socket.on("connect", () => setConnected(true))
325
+ socket.on("disconnect", () => setConnected(false))
326
+ socketRef.current = socket
327
+
328
+ return () => {
329
+ socket.off("connect")
330
+ socket.off("disconnect")
331
+ socket.disconnect()
332
+ socketRef.current = null
333
+ setConnected(false)
334
+ }
335
+ }, [user])
336
+
337
+ const value = useMemo(
338
+ () => ({ socket: socketRef.current, isConnected }),
339
+ [isConnected]
340
+ )
341
+
342
+ return <RealtimeContext.Provider value={value}>{children}</RealtimeContext.Provider>
343
+ }
344
+
345
+ export function useRealtime() {
346
+ return useContext(RealtimeContext)
347
+ }
348
+
349
+ // app/chat/page.tsx
350
+ // const { socket } = useRealtime()
351
+ // useEffect(() => {
352
+ // if (!socket) return
353
+ // const onMessage = event => {
354
+ // // Update local UI state, then debounce REST refresh if full state is needed.
355
+ // }
356
+ // socket.on("chat:message", onMessage)
357
+ // return () => socket.off("chat:message", onMessage)
358
+ // }, [socket])`,
359
+ notes: [
360
+ 'Create the Socket.IO client once in a top-level client provider after the current user is known.',
361
+ 'Use the websocket namespace path from live metadata, such as /chat, and keep the transport path as /socket.io.',
362
+ 'Proxy /socket.io through Next rewrites to the Enfyra app bridge /ws/socket.io so cookies remain same-origin.',
363
+ 'Pages/components should only subscribe/unsubscribe listeners; they should not create independent socket connections.',
364
+ 'Disconnect the singleton socket when the current user/session clears.',
365
+ ],
366
+ },
367
+ {
368
+ name: 'Angular singleton Socket.IO realtime service',
369
+ code: `// enfyra-realtime.service.ts
370
+ import { Injectable, computed, effect, signal } from "@angular/core"
371
+ import { io, Socket } from "socket.io-client"
372
+
373
+ import { EnfyraAuthService } from "./enfyra-auth.service"
374
+
375
+ @Injectable({ providedIn: "root" })
376
+ export class EnfyraRealtimeService {
377
+ private socket: Socket | null = null
378
+ private readonly connected = signal(false)
379
+ readonly isConnected = computed(() => this.connected())
380
+
381
+ constructor(private readonly auth: EnfyraAuthService) {
382
+ effect(() => {
383
+ const user = this.auth.user()
384
+ if (user) this.connect()
385
+ else this.disconnect()
386
+ })
387
+ }
388
+
389
+ connect() {
390
+ if (this.socket) return this.socket
391
+
392
+ this.socket = io("/chat", {
393
+ path: "/socket.io",
394
+ withCredentials: true,
395
+ reconnection: true,
396
+ reconnectionAttempts: Infinity,
397
+ reconnectionDelay: 2000,
398
+ reconnectionDelayMax: 30000
399
+ })
400
+
401
+ this.socket.on("connect", () => this.connected.set(true))
402
+ this.socket.on("disconnect", () => this.connected.set(false))
403
+ return this.socket
404
+ }
405
+
406
+ disconnect() {
407
+ this.socket?.disconnect()
408
+ this.socket = null
409
+ this.connected.set(false)
410
+ }
411
+
412
+ onMessage(handler: (event: unknown) => void) {
413
+ const activeSocket = this.connect()
414
+ activeSocket.on("chat:message", handler)
415
+ return () => activeSocket.off("chat:message", handler)
416
+ }
417
+ }`,
418
+ notes: [
419
+ 'Create one app-level Socket.IO connection after auth is known.',
420
+ 'Use the websocket namespace path from live metadata, such as /chat, and keep the transport path as /socket.io.',
421
+ 'Components subscribe with onMessage and call the returned cleanup function in ngOnDestroy.',
422
+ 'Do not create a new socket per routed component.',
423
+ ],
424
+ },
425
+ {
426
+ name: 'Google OAuth button',
427
+ code: `const redirect = new URL("/chat", window.location.origin)
428
+ const url = new URL("/api/auth/google", "https://demo.enfyra.io")
429
+ url.searchParams.set("redirect", redirect.toString())
430
+ url.searchParams.set("cookieBridgePrefix", "/enfyra")
431
+ window.location.href = url.toString()`,
432
+ notes: [
433
+ 'redirect must be absolute and must include the app origin.',
434
+ 'Start OAuth on the Enfyra app URL. Do not start it at the third app /enfyra proxy path.',
435
+ 'cookieBridgePrefix is the app proxy prefix that forwards to Enfyra API routes.',
436
+ 'Enfyra redirects through {redirect.origin}{cookieBridgePrefix}/auth/set-cookies before returning to redirect.',
437
+ 'After returning, call /enfyra/me to load the authenticated user; do not parse tokens from the URL in proxy-cookie mode.',
438
+ ],
439
+ },
440
+ ],
441
+ };
442
+ //# sourceMappingURL=mcp-example-connect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-example-connect.js","sourceRoot":"","sources":["../../src/lib/mcp-example-connect.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG;IAC3B,KAAK,EAAE,wCAAwC;IAC/C,OAAO,EAAE,iOAAiO;IAC1O,QAAQ,EAAE;QACR;YACE,IAAI,EAAE,wCAAwC;YAC9C,IAAI,EAAE;;;;;;;;;;;;GAYX;YACK,KAAK,EAAE;gBACL,8GAA8G;gBAC9G,yGAAyG;gBACzG,2KAA2K;aAC5K;SACF;QACD;YACE,IAAI,EAAE,sCAAsC;YAC5C,IAAI,EAAE;;;;;;;;;;;;;;;0BAeY;YAClB,KAAK,EAAE;gBACL,sEAAsE;gBACtE,sGAAsG;gBACtG,uGAAuG;aACxG;SACF;QACD;YACE,IAAI,EAAE,0CAA0C;YAChD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BZ;YACM,KAAK,EAAE;gBACL,0FAA0F;gBAC1F,iFAAiF;gBACjF,8HAA8H;gBAC9H,kDAAkD;aACnD;SACF;QACD;YACE,IAAI,EAAE,uCAAuC;YAC7C,IAAI,EAAE;;;;;;;;;6CAS+B;YACrC,KAAK,EAAE;gBACL,+IAA+I;gBAC/I,yHAAyH;gBACzH,uEAAuE;aACxE;SACF;QACD;YACE,IAAI,EAAE,+CAA+C;YACrD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EX;YACK,KAAK,EAAE;gBACL,gIAAgI;gBAChI,gHAAgH;gBAChH,2FAA2F;gBAC3F,0IAA0I;gBAC1I,uEAAuE;aACxE;SACF;QACD;YACE,IAAI,EAAE,iDAAiD;YACvD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqEZ;YACM,KAAK,EAAE;gBACL,qGAAqG;gBACrG,oHAAoH;gBACpH,8FAA8F;gBAC9F,8JAA8J;aAC/J;SACF;QACD;YACE,IAAI,EAAE,iDAAiD;YACvD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA+EE;YACR,KAAK,EAAE;gBACL,kGAAkG;gBAClG,gHAAgH;gBAChH,8GAA8G;gBAC9G,sHAAsH;gBACtH,uEAAuE;aACxE;SACF;QACD;YACE,IAAI,EAAE,8CAA8C;YACpD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgDZ;YACM,KAAK,EAAE;gBACL,gEAAgE;gBAChE,gHAAgH;gBAChH,4FAA4F;gBAC5F,kDAAkD;aACnD;SACF;QACD;YACE,IAAI,EAAE,qBAAqB;YAC3B,IAAI,EAAE;;;;sCAIwB;YAC9B,KAAK,EAAE;gBACL,4DAA4D;gBAC5D,yFAAyF;gBACzF,gFAAgF;gBAChF,+GAA+G;gBAC/G,yHAAyH;aAC1H;SACF;KACF;CACF,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare const extensionsExamples: {
2
+ title: string;
3
+ useWhen: string;
4
+ examples: {
5
+ name: string;
6
+ code: string;
7
+ notes: string[];
8
+ }[];
9
+ };