@agent-relay/cloud 2.0.23 → 6.0.4

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 (301) hide show
  1. package/dist/api-client.d.ts +33 -0
  2. package/dist/api-client.d.ts.map +1 -0
  3. package/dist/api-client.js +123 -0
  4. package/dist/api-client.js.map +1 -0
  5. package/dist/auth.d.ts +13 -0
  6. package/dist/auth.d.ts.map +1 -0
  7. package/dist/auth.js +299 -0
  8. package/dist/auth.js.map +1 -0
  9. package/dist/connect.d.ts +45 -0
  10. package/dist/connect.d.ts.map +1 -0
  11. package/dist/connect.js +166 -0
  12. package/dist/connect.js.map +1 -0
  13. package/dist/index.d.ts +7 -10
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +7 -37
  16. package/dist/index.js.map +1 -1
  17. package/dist/lib/ssh-interactive.d.ts +70 -0
  18. package/dist/lib/ssh-interactive.d.ts.map +1 -0
  19. package/dist/lib/ssh-interactive.js +440 -0
  20. package/dist/lib/ssh-interactive.js.map +1 -0
  21. package/dist/lib/ssh-runtime.d.ts +35 -0
  22. package/dist/lib/ssh-runtime.d.ts.map +1 -0
  23. package/dist/lib/ssh-runtime.js +52 -0
  24. package/dist/lib/ssh-runtime.js.map +1 -0
  25. package/dist/types.d.ts +76 -0
  26. package/dist/types.d.ts.map +1 -0
  27. package/dist/types.js +12 -0
  28. package/dist/types.js.map +1 -0
  29. package/dist/workflows.d.ts +49 -0
  30. package/dist/workflows.d.ts.map +1 -0
  31. package/dist/workflows.js +473 -0
  32. package/dist/workflows.js.map +1 -0
  33. package/package.json +12 -25
  34. package/dist/api/admin.d.ts +0 -8
  35. package/dist/api/admin.d.ts.map +0 -1
  36. package/dist/api/admin.js +0 -225
  37. package/dist/api/admin.js.map +0 -1
  38. package/dist/api/auth.d.ts +0 -20
  39. package/dist/api/auth.d.ts.map +0 -1
  40. package/dist/api/auth.js +0 -138
  41. package/dist/api/auth.js.map +0 -1
  42. package/dist/api/billing.d.ts +0 -7
  43. package/dist/api/billing.d.ts.map +0 -1
  44. package/dist/api/billing.js +0 -564
  45. package/dist/api/billing.js.map +0 -1
  46. package/dist/api/cli-pty-runner.d.ts +0 -53
  47. package/dist/api/cli-pty-runner.d.ts.map +0 -1
  48. package/dist/api/cli-pty-runner.js +0 -175
  49. package/dist/api/cli-pty-runner.js.map +0 -1
  50. package/dist/api/codex-auth-helper.d.ts +0 -21
  51. package/dist/api/codex-auth-helper.d.ts.map +0 -1
  52. package/dist/api/codex-auth-helper.js +0 -327
  53. package/dist/api/codex-auth-helper.js.map +0 -1
  54. package/dist/api/consensus.d.ts +0 -13
  55. package/dist/api/consensus.d.ts.map +0 -1
  56. package/dist/api/consensus.js +0 -261
  57. package/dist/api/consensus.js.map +0 -1
  58. package/dist/api/coordinators.d.ts +0 -8
  59. package/dist/api/coordinators.d.ts.map +0 -1
  60. package/dist/api/coordinators.js +0 -750
  61. package/dist/api/coordinators.js.map +0 -1
  62. package/dist/api/daemons.d.ts +0 -12
  63. package/dist/api/daemons.d.ts.map +0 -1
  64. package/dist/api/daemons.js +0 -535
  65. package/dist/api/daemons.js.map +0 -1
  66. package/dist/api/email-auth.d.ts +0 -11
  67. package/dist/api/email-auth.d.ts.map +0 -1
  68. package/dist/api/email-auth.js +0 -347
  69. package/dist/api/email-auth.js.map +0 -1
  70. package/dist/api/generic-webhooks.d.ts +0 -8
  71. package/dist/api/generic-webhooks.d.ts.map +0 -1
  72. package/dist/api/generic-webhooks.js +0 -129
  73. package/dist/api/generic-webhooks.js.map +0 -1
  74. package/dist/api/git.d.ts +0 -8
  75. package/dist/api/git.d.ts.map +0 -1
  76. package/dist/api/git.js +0 -269
  77. package/dist/api/git.js.map +0 -1
  78. package/dist/api/github-app.d.ts +0 -11
  79. package/dist/api/github-app.d.ts.map +0 -1
  80. package/dist/api/github-app.js +0 -223
  81. package/dist/api/github-app.js.map +0 -1
  82. package/dist/api/middleware/planLimits.d.ts +0 -43
  83. package/dist/api/middleware/planLimits.d.ts.map +0 -1
  84. package/dist/api/middleware/planLimits.js +0 -202
  85. package/dist/api/middleware/planLimits.js.map +0 -1
  86. package/dist/api/monitoring.d.ts +0 -11
  87. package/dist/api/monitoring.d.ts.map +0 -1
  88. package/dist/api/monitoring.js +0 -578
  89. package/dist/api/monitoring.js.map +0 -1
  90. package/dist/api/nango-auth.d.ts +0 -9
  91. package/dist/api/nango-auth.d.ts.map +0 -1
  92. package/dist/api/nango-auth.js +0 -741
  93. package/dist/api/nango-auth.js.map +0 -1
  94. package/dist/api/onboarding.d.ts +0 -15
  95. package/dist/api/onboarding.d.ts.map +0 -1
  96. package/dist/api/onboarding.js +0 -679
  97. package/dist/api/onboarding.js.map +0 -1
  98. package/dist/api/policy.d.ts +0 -8
  99. package/dist/api/policy.d.ts.map +0 -1
  100. package/dist/api/policy.js +0 -229
  101. package/dist/api/policy.js.map +0 -1
  102. package/dist/api/provider-env.d.ts +0 -26
  103. package/dist/api/provider-env.d.ts.map +0 -1
  104. package/dist/api/provider-env.js +0 -141
  105. package/dist/api/provider-env.js.map +0 -1
  106. package/dist/api/providers.d.ts +0 -7
  107. package/dist/api/providers.d.ts.map +0 -1
  108. package/dist/api/providers.js +0 -574
  109. package/dist/api/providers.js.map +0 -1
  110. package/dist/api/repos.d.ts +0 -8
  111. package/dist/api/repos.d.ts.map +0 -1
  112. package/dist/api/repos.js +0 -577
  113. package/dist/api/repos.js.map +0 -1
  114. package/dist/api/sessions.d.ts +0 -11
  115. package/dist/api/sessions.d.ts.map +0 -1
  116. package/dist/api/sessions.js +0 -302
  117. package/dist/api/sessions.js.map +0 -1
  118. package/dist/api/teams.d.ts +0 -7
  119. package/dist/api/teams.d.ts.map +0 -1
  120. package/dist/api/teams.js +0 -281
  121. package/dist/api/teams.js.map +0 -1
  122. package/dist/api/test-helpers.d.ts +0 -10
  123. package/dist/api/test-helpers.d.ts.map +0 -1
  124. package/dist/api/test-helpers.js +0 -745
  125. package/dist/api/test-helpers.js.map +0 -1
  126. package/dist/api/usage.d.ts +0 -7
  127. package/dist/api/usage.d.ts.map +0 -1
  128. package/dist/api/usage.js +0 -111
  129. package/dist/api/usage.js.map +0 -1
  130. package/dist/api/webhooks.d.ts +0 -8
  131. package/dist/api/webhooks.d.ts.map +0 -1
  132. package/dist/api/webhooks.js +0 -645
  133. package/dist/api/webhooks.js.map +0 -1
  134. package/dist/api/workspaces.d.ts +0 -25
  135. package/dist/api/workspaces.d.ts.map +0 -1
  136. package/dist/api/workspaces.js +0 -1799
  137. package/dist/api/workspaces.js.map +0 -1
  138. package/dist/billing/index.d.ts +0 -9
  139. package/dist/billing/index.d.ts.map +0 -1
  140. package/dist/billing/index.js +0 -9
  141. package/dist/billing/index.js.map +0 -1
  142. package/dist/billing/plans.d.ts +0 -39
  143. package/dist/billing/plans.d.ts.map +0 -1
  144. package/dist/billing/plans.js +0 -245
  145. package/dist/billing/plans.js.map +0 -1
  146. package/dist/billing/service.d.ts +0 -80
  147. package/dist/billing/service.d.ts.map +0 -1
  148. package/dist/billing/service.js +0 -388
  149. package/dist/billing/service.js.map +0 -1
  150. package/dist/billing/types.d.ts +0 -141
  151. package/dist/billing/types.d.ts.map +0 -1
  152. package/dist/billing/types.js +0 -7
  153. package/dist/billing/types.js.map +0 -1
  154. package/dist/config.d.ts +0 -5
  155. package/dist/config.d.ts.map +0 -1
  156. package/dist/config.js +0 -5
  157. package/dist/config.js.map +0 -1
  158. package/dist/db/bulk-ingest.d.ts +0 -89
  159. package/dist/db/bulk-ingest.d.ts.map +0 -1
  160. package/dist/db/bulk-ingest.js +0 -268
  161. package/dist/db/bulk-ingest.js.map +0 -1
  162. package/dist/db/drizzle.d.ts +0 -290
  163. package/dist/db/drizzle.d.ts.map +0 -1
  164. package/dist/db/drizzle.js +0 -1422
  165. package/dist/db/drizzle.js.map +0 -1
  166. package/dist/db/index.d.ts +0 -56
  167. package/dist/db/index.d.ts.map +0 -1
  168. package/dist/db/index.js +0 -70
  169. package/dist/db/index.js.map +0 -1
  170. package/dist/db/schema.d.ts +0 -5117
  171. package/dist/db/schema.d.ts.map +0 -1
  172. package/dist/db/schema.js +0 -656
  173. package/dist/db/schema.js.map +0 -1
  174. package/dist/provisioner/index.d.ts +0 -207
  175. package/dist/provisioner/index.d.ts.map +0 -1
  176. package/dist/provisioner/index.js +0 -2118
  177. package/dist/provisioner/index.js.map +0 -1
  178. package/dist/server.d.ts +0 -17
  179. package/dist/server.d.ts.map +0 -1
  180. package/dist/server.js +0 -2055
  181. package/dist/server.js.map +0 -1
  182. package/dist/services/auto-scaler.d.ts +0 -152
  183. package/dist/services/auto-scaler.d.ts.map +0 -1
  184. package/dist/services/auto-scaler.js +0 -439
  185. package/dist/services/auto-scaler.js.map +0 -1
  186. package/dist/services/capacity-manager.d.ts +0 -148
  187. package/dist/services/capacity-manager.d.ts.map +0 -1
  188. package/dist/services/capacity-manager.js +0 -449
  189. package/dist/services/capacity-manager.js.map +0 -1
  190. package/dist/services/ci-agent-spawner.d.ts +0 -49
  191. package/dist/services/ci-agent-spawner.d.ts.map +0 -1
  192. package/dist/services/ci-agent-spawner.js +0 -373
  193. package/dist/services/ci-agent-spawner.js.map +0 -1
  194. package/dist/services/cloud-message-bus.d.ts +0 -28
  195. package/dist/services/cloud-message-bus.d.ts.map +0 -1
  196. package/dist/services/cloud-message-bus.js +0 -19
  197. package/dist/services/cloud-message-bus.js.map +0 -1
  198. package/dist/services/compute-enforcement.d.ts +0 -57
  199. package/dist/services/compute-enforcement.d.ts.map +0 -1
  200. package/dist/services/compute-enforcement.js +0 -175
  201. package/dist/services/compute-enforcement.js.map +0 -1
  202. package/dist/services/coordinator.d.ts +0 -62
  203. package/dist/services/coordinator.d.ts.map +0 -1
  204. package/dist/services/coordinator.js +0 -389
  205. package/dist/services/coordinator.js.map +0 -1
  206. package/dist/services/index.d.ts +0 -17
  207. package/dist/services/index.d.ts.map +0 -1
  208. package/dist/services/index.js +0 -25
  209. package/dist/services/index.js.map +0 -1
  210. package/dist/services/intro-expiration.d.ts +0 -60
  211. package/dist/services/intro-expiration.d.ts.map +0 -1
  212. package/dist/services/intro-expiration.js +0 -252
  213. package/dist/services/intro-expiration.js.map +0 -1
  214. package/dist/services/mention-handler.d.ts +0 -65
  215. package/dist/services/mention-handler.d.ts.map +0 -1
  216. package/dist/services/mention-handler.js +0 -405
  217. package/dist/services/mention-handler.js.map +0 -1
  218. package/dist/services/nango.d.ts +0 -219
  219. package/dist/services/nango.d.ts.map +0 -1
  220. package/dist/services/nango.js +0 -424
  221. package/dist/services/nango.js.map +0 -1
  222. package/dist/services/persistence.d.ts +0 -131
  223. package/dist/services/persistence.d.ts.map +0 -1
  224. package/dist/services/persistence.js +0 -200
  225. package/dist/services/persistence.js.map +0 -1
  226. package/dist/services/planLimits.d.ts +0 -147
  227. package/dist/services/planLimits.d.ts.map +0 -1
  228. package/dist/services/planLimits.js +0 -335
  229. package/dist/services/planLimits.js.map +0 -1
  230. package/dist/services/presence-registry.d.ts +0 -56
  231. package/dist/services/presence-registry.d.ts.map +0 -1
  232. package/dist/services/presence-registry.js +0 -91
  233. package/dist/services/presence-registry.js.map +0 -1
  234. package/dist/services/scaling-orchestrator.d.ts +0 -159
  235. package/dist/services/scaling-orchestrator.d.ts.map +0 -1
  236. package/dist/services/scaling-orchestrator.js +0 -502
  237. package/dist/services/scaling-orchestrator.js.map +0 -1
  238. package/dist/services/scaling-policy.d.ts +0 -121
  239. package/dist/services/scaling-policy.d.ts.map +0 -1
  240. package/dist/services/scaling-policy.js +0 -415
  241. package/dist/services/scaling-policy.js.map +0 -1
  242. package/dist/services/ssh-security.d.ts +0 -31
  243. package/dist/services/ssh-security.d.ts.map +0 -1
  244. package/dist/services/ssh-security.js +0 -63
  245. package/dist/services/ssh-security.js.map +0 -1
  246. package/dist/services/workspace-keepalive.d.ts +0 -76
  247. package/dist/services/workspace-keepalive.d.ts.map +0 -1
  248. package/dist/services/workspace-keepalive.js +0 -234
  249. package/dist/services/workspace-keepalive.js.map +0 -1
  250. package/dist/shims/consensus.d.ts +0 -23
  251. package/dist/shims/consensus.d.ts.map +0 -1
  252. package/dist/shims/consensus.js +0 -5
  253. package/dist/shims/consensus.js.map +0 -1
  254. package/dist/webhooks/index.d.ts +0 -24
  255. package/dist/webhooks/index.d.ts.map +0 -1
  256. package/dist/webhooks/index.js +0 -29
  257. package/dist/webhooks/index.js.map +0 -1
  258. package/dist/webhooks/parsers/github.d.ts +0 -8
  259. package/dist/webhooks/parsers/github.d.ts.map +0 -1
  260. package/dist/webhooks/parsers/github.js +0 -234
  261. package/dist/webhooks/parsers/github.js.map +0 -1
  262. package/dist/webhooks/parsers/index.d.ts +0 -23
  263. package/dist/webhooks/parsers/index.d.ts.map +0 -1
  264. package/dist/webhooks/parsers/index.js +0 -30
  265. package/dist/webhooks/parsers/index.js.map +0 -1
  266. package/dist/webhooks/parsers/linear.d.ts +0 -9
  267. package/dist/webhooks/parsers/linear.d.ts.map +0 -1
  268. package/dist/webhooks/parsers/linear.js +0 -258
  269. package/dist/webhooks/parsers/linear.js.map +0 -1
  270. package/dist/webhooks/parsers/slack.d.ts +0 -9
  271. package/dist/webhooks/parsers/slack.d.ts.map +0 -1
  272. package/dist/webhooks/parsers/slack.js +0 -214
  273. package/dist/webhooks/parsers/slack.js.map +0 -1
  274. package/dist/webhooks/responders/github.d.ts +0 -8
  275. package/dist/webhooks/responders/github.d.ts.map +0 -1
  276. package/dist/webhooks/responders/github.js +0 -73
  277. package/dist/webhooks/responders/github.js.map +0 -1
  278. package/dist/webhooks/responders/index.d.ts +0 -23
  279. package/dist/webhooks/responders/index.d.ts.map +0 -1
  280. package/dist/webhooks/responders/index.js +0 -30
  281. package/dist/webhooks/responders/index.js.map +0 -1
  282. package/dist/webhooks/responders/linear.d.ts +0 -9
  283. package/dist/webhooks/responders/linear.d.ts.map +0 -1
  284. package/dist/webhooks/responders/linear.js +0 -149
  285. package/dist/webhooks/responders/linear.js.map +0 -1
  286. package/dist/webhooks/responders/slack.d.ts +0 -20
  287. package/dist/webhooks/responders/slack.d.ts.map +0 -1
  288. package/dist/webhooks/responders/slack.js +0 -178
  289. package/dist/webhooks/responders/slack.js.map +0 -1
  290. package/dist/webhooks/router.d.ts +0 -25
  291. package/dist/webhooks/router.d.ts.map +0 -1
  292. package/dist/webhooks/router.js +0 -504
  293. package/dist/webhooks/router.js.map +0 -1
  294. package/dist/webhooks/rules-engine.d.ts +0 -24
  295. package/dist/webhooks/rules-engine.d.ts.map +0 -1
  296. package/dist/webhooks/rules-engine.js +0 -287
  297. package/dist/webhooks/rules-engine.js.map +0 -1
  298. package/dist/webhooks/types.d.ts +0 -186
  299. package/dist/webhooks/types.d.ts.map +0 -1
  300. package/dist/webhooks/types.js +0 -8
  301. package/dist/webhooks/types.js.map +0 -1
@@ -1,741 +0,0 @@
1
- /**
2
- * Nango Auth API Routes
3
- *
4
- * Handles GitHub OAuth via Nango with two-connection pattern:
5
- * - github: User login (identity)
6
- * - github-app-oauth: Repository access
7
- */
8
- import { Router } from 'express';
9
- import { randomUUID } from 'crypto';
10
- import { requireAuth } from './auth.js';
11
- import { db } from '../db/index.js';
12
- import { nangoService, NANGO_INTEGRATIONS } from '../services/nango.js';
13
- export const nangoAuthRouter = Router();
14
- /**
15
- * GET /api/auth/nango/status
16
- * Check if Nango is configured
17
- */
18
- nangoAuthRouter.get('/status', (req, res) => {
19
- try {
20
- res.json({
21
- configured: true,
22
- integrations: NANGO_INTEGRATIONS,
23
- });
24
- }
25
- catch (_error) {
26
- res.json({
27
- configured: false,
28
- message: 'Nango not configured',
29
- });
30
- }
31
- });
32
- /**
33
- * GET /api/auth/nango/login-session
34
- * Create a Nango connect session for GitHub login
35
- */
36
- nangoAuthRouter.get('/login-session', async (req, res) => {
37
- try {
38
- const tempUserId = randomUUID();
39
- const session = await nangoService.createConnectSession([NANGO_INTEGRATIONS.GITHUB_USER], { id: tempUserId });
40
- res.json({ sessionToken: session.token, tempUserId });
41
- }
42
- catch (error) {
43
- console.error('Error creating login session:', error);
44
- res.status(500).json({ error: 'Failed to create login session' });
45
- }
46
- });
47
- /**
48
- * GET /api/auth/nango/login-status/:connectionId
49
- * Poll for login completion after Nango connect UI
50
- */
51
- nangoAuthRouter.get('/login-status/:connectionId', async (req, res) => {
52
- const connectionId = req.params.connectionId;
53
- try {
54
- // Check if a user exists with this incoming connection
55
- const user = await db.users.findByIncomingConnectionId(connectionId);
56
- if (!user) {
57
- return res.json({ ready: false });
58
- }
59
- // Issue session
60
- req.session.userId = user.id;
61
- // Clear incoming connection ID
62
- await db.users.clearIncomingConnectionId(user.id);
63
- // Check if user has any repos connected
64
- const repos = await db.repositories.findByUserId(user.id);
65
- const hasRepos = repos.length > 0;
66
- // Check if user needs to provide an email
67
- const needsEmail = !user.email;
68
- res.json({
69
- ready: true,
70
- hasRepos,
71
- needsEmail,
72
- user: {
73
- id: user.id,
74
- githubUsername: user.githubUsername,
75
- email: user.email,
76
- avatarUrl: user.avatarUrl,
77
- plan: user.plan,
78
- },
79
- });
80
- }
81
- catch (error) {
82
- console.error('Error checking login status:', error);
83
- res.status(500).json({ error: 'Failed to check login status' });
84
- }
85
- });
86
- /**
87
- * GET /api/auth/nango/repo-session
88
- * Create a Nango connect session for GitHub App OAuth (repo access)
89
- * Requires authentication
90
- */
91
- nangoAuthRouter.get('/repo-session', requireAuth, async (req, res) => {
92
- const userId = req.session.userId;
93
- try {
94
- const user = await db.users.findById(userId);
95
- if (!user) {
96
- return res.status(404).json({ error: 'User not found' });
97
- }
98
- const session = await nangoService.createConnectSession([NANGO_INTEGRATIONS.GITHUB_APP], { id: user.id, email: user.email || undefined });
99
- res.json({ sessionToken: session.token });
100
- }
101
- catch (error) {
102
- console.error('Error creating repo session:', error);
103
- res.status(500).json({ error: 'Failed to create repo session' });
104
- }
105
- });
106
- /**
107
- * GET /api/auth/nango/repo-status/:connectionId
108
- * Poll for repo sync completion after GitHub App OAuth
109
- * Requires authentication
110
- */
111
- nangoAuthRouter.get('/repo-status/:connectionId', requireAuth, async (req, res) => {
112
- const userId = req.session.userId;
113
- const _connectionId = req.params.connectionId;
114
- try {
115
- const user = await db.users.findById(userId);
116
- if (!user) {
117
- return res.status(404).json({ error: 'User not found' });
118
- }
119
- // Check for pending org approval
120
- if (user.pendingInstallationRequest) {
121
- return res.json({
122
- ready: false,
123
- pendingApproval: true,
124
- message: 'Waiting for organization admin approval',
125
- });
126
- }
127
- // Check if repos have been synced
128
- const repos = await db.repositories.findByUserId(userId);
129
- const reposFromConnection = repos.filter(r => r.syncStatus === 'synced' && r.nangoConnectionId);
130
- if (reposFromConnection.length === 0) {
131
- return res.json({ ready: false });
132
- }
133
- // Check workspace status for frontend visibility
134
- const workspaces = await db.workspaces.findByUserId(userId);
135
- const primaryWorkspace = workspaces[0];
136
- res.json({
137
- ready: true,
138
- repos: reposFromConnection.map(r => ({
139
- id: r.id,
140
- fullName: r.githubFullName,
141
- isPrivate: r.isPrivate,
142
- defaultBranch: r.defaultBranch,
143
- })),
144
- workspace: primaryWorkspace ? {
145
- id: primaryWorkspace.id,
146
- name: primaryWorkspace.name,
147
- status: primaryWorkspace.status,
148
- publicUrl: primaryWorkspace.publicUrl,
149
- } : null,
150
- workspaceProvisioning: primaryWorkspace?.status === 'provisioning',
151
- });
152
- }
153
- catch (error) {
154
- console.error('Error checking repo status:', error);
155
- res.status(500).json({ error: 'Failed to check repo status' });
156
- }
157
- });
158
- // ============================================================================
159
- // Nango Webhook Handler
160
- // ============================================================================
161
- /**
162
- * POST /api/auth/nango/webhook
163
- * Handle Nango webhooks for auth and sync events
164
- */
165
- nangoAuthRouter.post('/webhook', async (req, res) => {
166
- const rawBody = req.rawBody || JSON.stringify(req.body);
167
- // Verify webhook signature if present
168
- const hasSignature = req.headers['x-nango-signature'] || req.headers['x-nango-hmac-sha256'];
169
- if (hasSignature) {
170
- if (!nangoService.verifyWebhookSignature(rawBody, req.headers)) {
171
- console.error('[nango-webhook] Invalid signature');
172
- return res.status(401).json({ error: 'Invalid signature' });
173
- }
174
- }
175
- const payload = req.body;
176
- console.log(`[nango-webhook] Received ${payload.type} event`);
177
- try {
178
- switch (payload.type) {
179
- case 'auth':
180
- await handleAuthWebhook(payload);
181
- break;
182
- case 'sync':
183
- console.log('[nango-webhook] Sync event received');
184
- break;
185
- case 'forward':
186
- await handleForwardWebhook(payload);
187
- break;
188
- default:
189
- console.log(`[nango-webhook] Unhandled event type: ${payload.type}`);
190
- }
191
- res.json({ success: true });
192
- }
193
- catch (error) {
194
- console.error('[nango-webhook] Error processing webhook:', error);
195
- res.status(500).json({ error: 'Failed to process webhook' });
196
- }
197
- });
198
- /**
199
- * Handle Nango auth webhook
200
- */
201
- async function handleAuthWebhook(payload) {
202
- const { connectionId, providerConfigKey, endUser } = payload;
203
- console.log(`[nango-webhook] Auth event for ${providerConfigKey} (${connectionId})`);
204
- if (providerConfigKey === NANGO_INTEGRATIONS.GITHUB_USER) {
205
- await handleLoginWebhook(connectionId, endUser);
206
- }
207
- else if (providerConfigKey === NANGO_INTEGRATIONS.GITHUB_APP) {
208
- await handleRepoAuthWebhook(connectionId, endUser);
209
- }
210
- }
211
- /**
212
- * Check user's repo access and auto-add them to workspaces
213
- * Uses GitHub user OAuth to query accessible repos and persists them to database
214
- */
215
- async function checkAndAutoAddToWorkspaces(userId, connectionId) {
216
- try {
217
- const user = await db.users.findById(userId);
218
- if (!user)
219
- return;
220
- console.log(`[nango-webhook] Checking workspace auto-add for ${user.githubUsername}`);
221
- // Query repos the user has access to via GitHub OAuth
222
- const { repositories } = await nangoService.listUserAccessibleRepos(connectionId, {
223
- perPage: 100,
224
- type: 'all',
225
- });
226
- const workspacesToJoin = new Set();
227
- // Check for workspace memberships - only persist repos that match existing workspaces
228
- for (const repo of repositories) {
229
- // Check if any user has this repo linked to a workspace
230
- const allRepoRecords = await db.repositories.findByGithubFullName(repo.fullName);
231
- let matchedWorkspaceId = null;
232
- for (const record of allRepoRecords) {
233
- if (record.workspaceId) {
234
- workspacesToJoin.add(record.workspaceId);
235
- matchedWorkspaceId = record.workspaceId; // Save the workspaceId to copy
236
- }
237
- }
238
- // Only persist repos that are linked to workspaces
239
- if (matchedWorkspaceId) {
240
- await db.repositories.upsert({
241
- userId: user.id,
242
- githubFullName: repo.fullName,
243
- githubId: repo.id,
244
- isPrivate: repo.isPrivate,
245
- defaultBranch: repo.defaultBranch,
246
- nangoConnectionId: connectionId,
247
- workspaceId: matchedWorkspaceId, // Copy the workspaceId
248
- syncStatus: 'synced',
249
- lastSyncedAt: new Date(),
250
- });
251
- }
252
- }
253
- // Auto-add user to workspaces
254
- for (const workspaceId of workspacesToJoin) {
255
- const existingMembership = await db.workspaceMembers.findMembership(workspaceId, userId);
256
- if (!existingMembership) {
257
- const workspace = await db.workspaces.findById(workspaceId);
258
- if (workspace) {
259
- console.log(`[nango-webhook] Auto-adding ${user.githubUsername} to workspace ${workspace.name}`);
260
- await db.workspaceMembers.addMember({
261
- workspaceId,
262
- userId,
263
- role: 'member',
264
- invitedBy: workspace.userId,
265
- });
266
- await db.workspaceMembers.acceptInvite(workspaceId, userId);
267
- }
268
- }
269
- }
270
- console.log(`[nango-webhook] Synced ${repositories.length} repos, auto-added ${user.githubUsername} to ${workspacesToJoin.size} workspaces`);
271
- }
272
- catch (error) {
273
- console.error(`[nango-webhook] Error checking workspace auto-add:`, error);
274
- // Non-fatal - don't throw
275
- }
276
- }
277
- /**
278
- * Fetch and sync user emails from GitHub
279
- * Requires 'user:email' scope to be configured in Nango's GitHub integration
280
- */
281
- async function syncGitHubEmails(userId, connectionId) {
282
- try {
283
- const emails = await nangoService.getGithubUserEmails(connectionId);
284
- if (emails.length === 0) {
285
- console.log(`[nango-webhook] No emails returned from GitHub (scope may not be granted)`);
286
- return null;
287
- }
288
- // Sync all verified emails to user_emails table
289
- const verifiedEmails = emails.filter(e => e.verified);
290
- if (verifiedEmails.length > 0) {
291
- await db.userEmails.syncFromGitHub(userId, verifiedEmails);
292
- console.log(`[nango-webhook] Synced ${verifiedEmails.length} verified emails for user ${userId}`);
293
- }
294
- // Return the primary verified email
295
- const primaryEmail = emails.find(e => e.primary && e.verified)?.email;
296
- return primaryEmail || null;
297
- }
298
- catch (error) {
299
- console.error('[nango-webhook] Error syncing GitHub emails:', error);
300
- return null;
301
- }
302
- }
303
- /**
304
- * Handle GitHub login webhook
305
- *
306
- * Three scenarios:
307
- * 1. New user - Create user record, keep connection as permanent
308
- * 2. Returning user with existing connection - Store incoming ID for polling, delete temp connection
309
- * 3. Existing user, first connection - Set connection ID as permanent
310
- */
311
- async function handleLoginWebhook(connectionId, _endUser) {
312
- // Get GitHub user info via Nango proxy
313
- const githubUser = await nangoService.getGithubUser(connectionId);
314
- const githubId = String(githubUser.id);
315
- // Check if user already exists by GitHub ID
316
- let existingUser = await db.users.findByGithubId(githubId);
317
- // If not found by GitHub ID, check by email (for email-signup users connecting GitHub)
318
- if (!existingUser && githubUser.email) {
319
- const userByEmail = await db.users.findByEmail(githubUser.email);
320
- if (userByEmail) {
321
- // Email-signup user is connecting their GitHub account
322
- console.log(`[nango-webhook] Linking GitHub to existing email user: ${githubUser.login} -> ${userByEmail.email}`);
323
- // Update the existing user with GitHub info
324
- await db.users.update(userByEmail.id, {
325
- githubId,
326
- githubUsername: githubUser.login,
327
- avatarUrl: githubUser.avatar_url || null,
328
- nangoConnectionId: connectionId,
329
- incomingConnectionId: connectionId,
330
- });
331
- // Sync GitHub emails
332
- await syncGitHubEmails(userByEmail.id, connectionId);
333
- // Update connection with user ID
334
- await nangoService.updateEndUser(connectionId, NANGO_INTEGRATIONS.GITHUB_USER, {
335
- id: userByEmail.id,
336
- email: userByEmail.email || undefined,
337
- });
338
- // Check for auto-add to workspaces
339
- await checkAndAutoAddToWorkspaces(userByEmail.id, connectionId);
340
- return;
341
- }
342
- }
343
- // SCENARIO 1: New user (no existing user by GitHub ID or email)
344
- if (!existingUser) {
345
- // First, get the primary email from GitHub API (requires user:email scope)
346
- // We'll create the user first, then sync emails
347
- const newUser = await db.users.upsert({
348
- githubId,
349
- githubUsername: githubUser.login,
350
- email: githubUser.email || null,
351
- avatarUrl: githubUser.avatar_url || null,
352
- nangoConnectionId: connectionId,
353
- incomingConnectionId: connectionId,
354
- });
355
- // Sync all GitHub emails and get primary email
356
- const primaryEmail = await syncGitHubEmails(newUser.id, connectionId);
357
- // If we got a primary email from the API and user doesn't have one, update it
358
- if (primaryEmail && !newUser.email) {
359
- await db.users.update(newUser.id, { email: primaryEmail });
360
- }
361
- // Update connection with real user ID
362
- await nangoService.updateEndUser(connectionId, NANGO_INTEGRATIONS.GITHUB_USER, {
363
- id: newUser.id,
364
- email: primaryEmail || newUser.email || undefined,
365
- });
366
- console.log(`[nango-webhook] New user created: ${githubUser.login}`);
367
- // Check for auto-add to workspaces based on repo access
368
- await checkAndAutoAddToWorkspaces(newUser.id, connectionId);
369
- return;
370
- }
371
- // SCENARIO 2: Returning user with existing connection - delete temp connection
372
- if (existingUser.nangoConnectionId && existingUser.nangoConnectionId !== connectionId) {
373
- console.log(`[nango-webhook] Returning user: ${githubUser.login}`, {
374
- permanentConnectionId: existingUser.nangoConnectionId,
375
- incomingConnectionId: connectionId,
376
- });
377
- // Store incoming connection ID for polling
378
- await db.users.update(existingUser.id, {
379
- incomingConnectionId: connectionId,
380
- githubUsername: githubUser.login,
381
- avatarUrl: githubUser.avatar_url || null,
382
- });
383
- // Sync GitHub emails using the temporary connection before we delete it
384
- await syncGitHubEmails(existingUser.id, connectionId);
385
- // Delete the temporary connection from Nango to prevent duplicates
386
- try {
387
- await nangoService.deleteConnection(connectionId, NANGO_INTEGRATIONS.GITHUB_USER);
388
- console.log(`[nango-webhook] Deleted temp connection for returning user`);
389
- }
390
- catch (error) {
391
- console.error(`[nango-webhook] Failed to delete temp connection:`, error);
392
- // Non-fatal - continue anyway
393
- }
394
- // Check for auto-add using permanent connection
395
- await checkAndAutoAddToWorkspaces(existingUser.id, existingUser.nangoConnectionId);
396
- return;
397
- }
398
- // SCENARIO 3: Existing user, first connection (or same connection)
399
- console.log(`[nango-webhook] First/same connection for existing user: ${githubUser.login}`);
400
- await db.users.update(existingUser.id, {
401
- nangoConnectionId: connectionId,
402
- incomingConnectionId: connectionId,
403
- githubUsername: githubUser.login,
404
- avatarUrl: githubUser.avatar_url || null,
405
- });
406
- // Sync GitHub emails
407
- const primaryEmail = await syncGitHubEmails(existingUser.id, connectionId);
408
- // Update connection with user ID
409
- await nangoService.updateEndUser(connectionId, NANGO_INTEGRATIONS.GITHUB_USER, {
410
- id: existingUser.id,
411
- email: primaryEmail || existingUser.email || undefined,
412
- });
413
- // Check for auto-add to workspaces
414
- await checkAndAutoAddToWorkspaces(existingUser.id, connectionId);
415
- }
416
- /**
417
- * Handle Nango forward webhook (GitHub events forwarded by Nango)
418
- */
419
- async function handleForwardWebhook(payload) {
420
- const githubPayload = payload.payload;
421
- console.log(`[nango-webhook] Forward event: action=${githubPayload.action} from ${payload.providerConfigKey}`);
422
- // Only process GitHub App events
423
- if (payload.providerConfigKey !== NANGO_INTEGRATIONS.GITHUB_APP) {
424
- console.log('[nango-webhook] Ignoring forward event from non-GitHub-App integration');
425
- return;
426
- }
427
- try {
428
- // Determine event type from payload structure
429
- if (githubPayload.installation && githubPayload.action === 'created' && githubPayload.repositories) {
430
- // Installation created event
431
- await handleInstallationForward(githubPayload, payload.connectionId);
432
- }
433
- else if (githubPayload.repositories_added || githubPayload.repositories_removed) {
434
- // Installation repositories added/removed
435
- await handleInstallationRepositoriesForward(githubPayload, payload.connectionId);
436
- }
437
- else {
438
- console.log(`[nango-webhook] Unhandled forward event structure: action=${githubPayload.action}`);
439
- }
440
- }
441
- catch (error) {
442
- console.error(`[nango-webhook] Error processing forward event:`, error);
443
- throw error;
444
- }
445
- }
446
- /**
447
- * Handle GitHub installation events forwarded by Nango
448
- */
449
- async function handleInstallationForward(body, connectionId) {
450
- const { action, installation, repositories, sender } = body;
451
- if (!installation || !sender)
452
- return;
453
- const installationId = String(installation.id);
454
- console.log(`[nango-webhook] Installation ${action}: ${installation.account.login} (${installationId})`);
455
- if (action === 'created') {
456
- // Find user by GitHub ID
457
- const user = await db.users.findByGithubId(String(sender.id));
458
- // Create/update installation record
459
- await db.githubInstallations.upsert({
460
- installationId,
461
- accountType: installation.account.type.toLowerCase(),
462
- accountLogin: installation.account.login,
463
- accountId: String(installation.account.id),
464
- installedById: user?.id ?? null,
465
- permissions: installation.permissions,
466
- events: installation.events,
467
- });
468
- // Sync repositories if provided
469
- if (repositories && user) {
470
- const dbInstallation = await db.githubInstallations.findByInstallationId(installationId);
471
- if (dbInstallation) {
472
- const workspacesToJoin = new Set();
473
- for (const repo of repositories) {
474
- const syncedRepo = await db.repositories.upsert({
475
- userId: user.id,
476
- githubFullName: repo.full_name,
477
- githubId: repo.id,
478
- isPrivate: repo.private,
479
- installationId: dbInstallation.id,
480
- nangoConnectionId: connectionId,
481
- syncStatus: 'synced',
482
- lastSyncedAt: new Date(),
483
- });
484
- // Check if repo is part of an existing workspace
485
- // Look for ANY user's record of this repo that has a workspaceId
486
- if (syncedRepo.workspaceId) {
487
- workspacesToJoin.add(syncedRepo.workspaceId);
488
- }
489
- else {
490
- // Check if other users have this repo linked to a workspace
491
- const allRepoRecords = await db.repositories.findByGithubFullName(repo.full_name);
492
- for (const otherRecord of allRepoRecords) {
493
- if (otherRecord.workspaceId && otherRecord.userId !== user.id) {
494
- workspacesToJoin.add(otherRecord.workspaceId);
495
- }
496
- }
497
- }
498
- }
499
- // Auto-join user to workspaces for repos they have access to
500
- for (const workspaceId of workspacesToJoin) {
501
- const existingMembership = await db.workspaceMembers.findMembership(workspaceId, user.id);
502
- if (!existingMembership) {
503
- const workspace = await db.workspaces.findById(workspaceId);
504
- if (workspace) {
505
- console.log(`[nango-webhook] Auto-adding ${user.githubUsername} to workspace ${workspace.name}`);
506
- await db.workspaceMembers.addMember({
507
- workspaceId,
508
- userId: user.id,
509
- role: 'member',
510
- invitedBy: workspace.userId,
511
- });
512
- await db.workspaceMembers.acceptInvite(workspaceId, user.id);
513
- }
514
- }
515
- }
516
- console.log(`[nango-webhook] Installation created for ${installation.account.login}, auto-joined ${workspacesToJoin.size} workspaces`);
517
- }
518
- }
519
- }
520
- }
521
- /**
522
- * Handle installation_repositories events forwarded by Nango
523
- */
524
- async function handleInstallationRepositoriesForward(body, connectionId) {
525
- const { action, installation, repositories_added, repositories_removed, sender } = body;
526
- console.log(`[nango-webhook] handleInstallationRepositoriesForward called`, {
527
- action,
528
- installation: installation?.id,
529
- sender: sender?.login,
530
- connectionId,
531
- repositories_added: repositories_added?.map(r => r.full_name),
532
- repositories_removed: repositories_removed?.map(r => r.full_name),
533
- });
534
- if (!installation || !sender) {
535
- console.log(`[nango-webhook] Missing installation or sender, skipping`);
536
- return;
537
- }
538
- const installationId = String(installation.id);
539
- console.log(`[nango-webhook] Repositories ${action} for ${installation.account.login}`);
540
- // Find installation in database
541
- const dbInstallation = await db.githubInstallations.findByInstallationId(installationId);
542
- if (!dbInstallation) {
543
- console.error(`[nango-webhook] Installation ${installationId} not found in database`);
544
- return;
545
- }
546
- console.log(`[nango-webhook] Found installation: ${dbInstallation.id}`);
547
- // Find user who triggered this
548
- const user = await db.users.findByGithubId(String(sender.id));
549
- if (!user) {
550
- console.error(`[nango-webhook] User ${sender.login} (github id: ${sender.id}) not found in database`);
551
- return;
552
- }
553
- console.log(`[nango-webhook] Found user: ${user.id} (${user.githubUsername})`);
554
- console.log(`[nango-webhook] Processing action: ${action}, repos_added: ${repositories_added?.length}, repos_removed: ${repositories_removed?.length}`);
555
- if (action === 'added' && repositories_added) {
556
- console.log(`[nango-webhook] Adding ${repositories_added.length} repos for user ${user.id}`);
557
- const workspacesToJoin = new Set();
558
- for (const repo of repositories_added) {
559
- console.log(`[nango-webhook] Upserting repo: ${repo.full_name}`);
560
- const syncedRepo = await db.repositories.upsert({
561
- userId: user.id,
562
- githubFullName: repo.full_name,
563
- githubId: repo.id,
564
- isPrivate: repo.private,
565
- installationId: dbInstallation.id,
566
- nangoConnectionId: connectionId,
567
- syncStatus: 'synced',
568
- lastSyncedAt: new Date(),
569
- });
570
- console.log(`[nango-webhook] Upserted repo: ${syncedRepo.id}, syncStatus: ${syncedRepo.syncStatus}, nangoConnectionId: ${syncedRepo.nangoConnectionId}`);
571
- // Check if repo is part of an existing workspace
572
- // Look for ANY user's record of this repo that has a workspaceId
573
- if (syncedRepo.workspaceId) {
574
- workspacesToJoin.add(syncedRepo.workspaceId);
575
- }
576
- else {
577
- // Check if other users have this repo linked to a workspace
578
- const allRepoRecords = await db.repositories.findByGithubFullName(repo.full_name);
579
- for (const otherRecord of allRepoRecords) {
580
- if (otherRecord.workspaceId && otherRecord.userId !== user.id) {
581
- workspacesToJoin.add(otherRecord.workspaceId);
582
- }
583
- }
584
- }
585
- }
586
- // Auto-join user to workspaces for repos they have access to
587
- for (const workspaceId of workspacesToJoin) {
588
- const existingMembership = await db.workspaceMembers.findMembership(workspaceId, user.id);
589
- if (!existingMembership) {
590
- const workspace = await db.workspaces.findById(workspaceId);
591
- if (workspace) {
592
- console.log(`[nango-webhook] Auto-adding ${user.githubUsername} to workspace ${workspace.name}`);
593
- await db.workspaceMembers.addMember({
594
- workspaceId,
595
- userId: user.id,
596
- role: 'member',
597
- invitedBy: workspace.userId,
598
- });
599
- await db.workspaceMembers.acceptInvite(workspaceId, user.id);
600
- }
601
- }
602
- }
603
- console.log(`[nango-webhook] Added ${repositories_added.length} repositories, auto-joined ${workspacesToJoin.size} workspaces`);
604
- }
605
- if (action === 'removed' && repositories_removed) {
606
- for (const repo of repositories_removed) {
607
- const repos = await db.repositories.findByUserId(user.id);
608
- const existingRepo = repos.find(r => r.githubFullName === repo.full_name);
609
- if (existingRepo) {
610
- await db.repositories.updateSyncStatus(existingRepo.id, 'access_removed');
611
- }
612
- }
613
- console.log(`[nango-webhook] Removed access to ${repositories_removed.length} repositories`);
614
- }
615
- }
616
- /**
617
- * Handle GitHub App OAuth webhook (repo access)
618
- */
619
- async function handleRepoAuthWebhook(connectionId, endUser) {
620
- let userId = endUser?.id;
621
- // Fallback: If endUser.id not in webhook, fetch connection metadata from Nango
622
- if (!userId) {
623
- console.log('[nango-webhook] No user ID in webhook payload, fetching from connection metadata...');
624
- try {
625
- const connection = await nangoService.getConnection(connectionId, NANGO_INTEGRATIONS.GITHUB_APP);
626
- userId = connection.end_user?.id;
627
- console.log(`[nango-webhook] Got user ID from connection: ${userId || 'not found'}`);
628
- }
629
- catch (err) {
630
- console.error('[nango-webhook] Failed to fetch connection metadata:', err);
631
- }
632
- }
633
- if (!userId) {
634
- console.error('[nango-webhook] No user ID found - cannot sync repos');
635
- return;
636
- }
637
- const user = await db.users.findById(userId);
638
- if (!user) {
639
- console.error(`[nango-webhook] User ${userId} not found`);
640
- return;
641
- }
642
- try {
643
- // Get the GitHub App installation ID
644
- const githubInstallationId = await nangoService.getGithubAppInstallationId(connectionId);
645
- let installationUuid = null;
646
- if (githubInstallationId) {
647
- // Find or create the github_installations record
648
- let installation = await db.githubInstallations.findByInstallationId(String(githubInstallationId));
649
- if (!installation) {
650
- // Create a new installation record
651
- // We need to get more info about the installation - for now use user info
652
- installation = await db.githubInstallations.upsert({
653
- installationId: String(githubInstallationId),
654
- accountType: 'user', // Could be 'organization' - we'd need to detect this
655
- accountLogin: user.githubUsername || 'unknown',
656
- accountId: user.githubId || 'unknown',
657
- installedById: user.id,
658
- permissions: {},
659
- events: [],
660
- });
661
- console.log(`[nango-webhook] Created installation record for ${githubInstallationId}`);
662
- }
663
- installationUuid = installation.id;
664
- }
665
- else {
666
- console.warn('[nango-webhook] Could not get installation ID from Nango connection');
667
- }
668
- // Fetch repos the user has access to
669
- const { repositories: repos } = await nangoService.listGithubAppRepos(connectionId);
670
- // Track workspaces to auto-join
671
- const workspacesToJoin = new Set();
672
- // Sync repos to database
673
- for (const repo of repos) {
674
- const syncedRepo = await db.repositories.upsert({
675
- userId: user.id,
676
- githubFullName: repo.full_name,
677
- githubId: repo.id,
678
- isPrivate: repo.private,
679
- defaultBranch: repo.default_branch,
680
- nangoConnectionId: connectionId,
681
- installationId: installationUuid,
682
- syncStatus: 'synced',
683
- lastSyncedAt: new Date(),
684
- });
685
- // Check if this repo is part of an existing workspace
686
- // Look for ANY user's record of this repo that has a workspaceId
687
- if (syncedRepo.workspaceId) {
688
- workspacesToJoin.add(syncedRepo.workspaceId);
689
- }
690
- else {
691
- // Check if other users have this repo linked to a workspace
692
- const allRepoRecords = await db.repositories.findByGithubFullName(repo.full_name);
693
- for (const otherRecord of allRepoRecords) {
694
- if (otherRecord.workspaceId && otherRecord.userId !== user.id) {
695
- workspacesToJoin.add(otherRecord.workspaceId);
696
- }
697
- }
698
- }
699
- }
700
- // Auto-join user to workspaces for repos they have access to
701
- for (const workspaceId of workspacesToJoin) {
702
- // Check if already a member
703
- const existingMembership = await db.workspaceMembers.findMembership(workspaceId, user.id);
704
- if (!existingMembership) {
705
- // Get workspace owner to use as invitedBy
706
- const workspace = await db.workspaces.findById(workspaceId);
707
- if (workspace) {
708
- console.log(`[nango-webhook] Auto-adding ${user.githubUsername} to workspace ${workspace.name}`);
709
- await db.workspaceMembers.addMember({
710
- workspaceId,
711
- userId: user.id,
712
- role: 'member',
713
- invitedBy: workspace.userId, // Workspace owner invited them
714
- });
715
- // Auto-accept since they have GitHub repo access
716
- await db.workspaceMembers.acceptInvite(workspaceId, user.id);
717
- }
718
- }
719
- }
720
- // Clear any pending installation request
721
- await db.users.clearPendingInstallationRequest(user.id);
722
- console.log(`[nango-webhook] Synced ${repos.length} repos for ${user.githubUsername} (installation: ${githubInstallationId || 'unknown'}), auto-joined ${workspacesToJoin.size} workspaces`);
723
- // Note: We intentionally do NOT auto-provision workspaces here.
724
- // Users should go through the onboarding flow at /app to:
725
- // 1. Name their workspace
726
- // 2. Choose which repos to include
727
- // 3. Understand what they're creating
728
- }
729
- catch (error) {
730
- const err = error;
731
- if (err.message?.includes('403')) {
732
- // Org approval pending
733
- await db.users.setPendingInstallationRequest(user.id);
734
- console.log(`[nango-webhook] Org approval pending for ${user.githubUsername}`);
735
- }
736
- else {
737
- throw error;
738
- }
739
- }
740
- }
741
- //# sourceMappingURL=nango-auth.js.map