workos 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. package/README.md +8 -145
  2. package/dist/bin.js +129 -50
  3. package/dist/bin.js.map +1 -1
  4. package/dist/commands/api/index.js +18 -10
  5. package/dist/commands/api/index.js.map +1 -1
  6. package/dist/commands/api/interactive.js +11 -11
  7. package/dist/commands/api/interactive.js.map +1 -1
  8. package/dist/commands/claim.js +28 -16
  9. package/dist/commands/claim.js.map +1 -1
  10. package/dist/commands/connection.js +3 -3
  11. package/dist/commands/connection.js.map +1 -1
  12. package/dist/commands/debug.js +6 -6
  13. package/dist/commands/debug.js.map +1 -1
  14. package/dist/commands/dev.d.ts +7 -8
  15. package/dist/commands/dev.js +14 -14
  16. package/dist/commands/dev.js.map +1 -1
  17. package/dist/commands/directory.js +3 -3
  18. package/dist/commands/directory.js.map +1 -1
  19. package/dist/commands/doctor.js +2 -2
  20. package/dist/commands/doctor.js.map +1 -1
  21. package/dist/commands/emulate.d.ts +1 -0
  22. package/dist/commands/emulate.js +3 -2
  23. package/dist/commands/emulate.js.map +1 -1
  24. package/dist/commands/env.d.ts +10 -0
  25. package/dist/commands/env.js +94 -18
  26. package/dist/commands/env.js.map +1 -1
  27. package/dist/commands/install.js +8 -13
  28. package/dist/commands/install.js.map +1 -1
  29. package/dist/commands/login.d.ts +25 -15
  30. package/dist/commands/login.js +126 -71
  31. package/dist/commands/login.js.map +1 -1
  32. package/dist/commands/logout.js +4 -4
  33. package/dist/commands/logout.js.map +1 -1
  34. package/dist/commands/mcp.js +7 -16
  35. package/dist/commands/mcp.js.map +1 -1
  36. package/dist/commands/migrations.js +2 -1
  37. package/dist/commands/migrations.js.map +1 -1
  38. package/dist/commands/seed.js +5 -4
  39. package/dist/commands/seed.js.map +1 -1
  40. package/dist/commands/setup.d.ts +50 -0
  41. package/dist/commands/setup.js +237 -0
  42. package/dist/commands/setup.js.map +1 -0
  43. package/dist/commands/vault-run.js +3 -2
  44. package/dist/commands/vault-run.js.map +1 -1
  45. package/dist/commands/verify-login.d.ts +25 -0
  46. package/dist/commands/verify-login.js +158 -0
  47. package/dist/commands/verify-login.js.map +1 -0
  48. package/dist/doctor/issues.js +3 -2
  49. package/dist/doctor/issues.js.map +1 -1
  50. package/dist/doctor/output.js +2 -1
  51. package/dist/doctor/output.js.map +1 -1
  52. package/dist/integrations/dotnet/index.js +1 -1
  53. package/dist/integrations/dotnet/index.js.map +1 -1
  54. package/dist/integrations/elixir/index.js +1 -1
  55. package/dist/integrations/elixir/index.js.map +1 -1
  56. package/dist/integrations/go/index.js +1 -1
  57. package/dist/integrations/go/index.js.map +1 -1
  58. package/dist/integrations/nextjs/index.js +8 -5
  59. package/dist/integrations/nextjs/index.js.map +1 -1
  60. package/dist/integrations/nextjs/utils.d.ts +1 -1
  61. package/dist/integrations/nextjs/utils.js +21 -6
  62. package/dist/integrations/nextjs/utils.js.map +1 -1
  63. package/dist/integrations/react-router/index.js +5 -5
  64. package/dist/integrations/react-router/index.js.map +1 -1
  65. package/dist/integrations/react-router/utils.js +28 -12
  66. package/dist/integrations/react-router/utils.js.map +1 -1
  67. package/dist/integrations/ruby/index.js +1 -1
  68. package/dist/integrations/ruby/index.js.map +1 -1
  69. package/dist/lib/adapters/cli-adapter.d.ts +33 -4
  70. package/dist/lib/adapters/cli-adapter.js +251 -135
  71. package/dist/lib/adapters/cli-adapter.js.map +1 -1
  72. package/dist/lib/adapters/dashboard-adapter.js +3 -3
  73. package/dist/lib/adapters/dashboard-adapter.js.map +1 -1
  74. package/dist/lib/adapters/headless-adapter.d.ts +7 -0
  75. package/dist/lib/adapters/headless-adapter.js +42 -5
  76. package/dist/lib/adapters/headless-adapter.js.map +1 -1
  77. package/dist/lib/agent-interface.js +15 -1
  78. package/dist/lib/agent-interface.js.map +1 -1
  79. package/dist/lib/agent-runner.js +1 -1
  80. package/dist/lib/agent-runner.js.map +1 -1
  81. package/dist/lib/api-key.js +2 -1
  82. package/dist/lib/api-key.js.map +1 -1
  83. package/dist/lib/completion-data.d.ts +33 -0
  84. package/dist/lib/completion-data.js +33 -0
  85. package/dist/lib/completion-data.js.map +1 -0
  86. package/dist/lib/config-store.d.ts +13 -0
  87. package/dist/lib/config-store.js +24 -0
  88. package/dist/lib/config-store.js.map +1 -1
  89. package/dist/lib/config.d.ts +1 -1
  90. package/dist/lib/config.js +1 -1
  91. package/dist/lib/config.js.map +1 -1
  92. package/dist/lib/constants.d.ts +8 -0
  93. package/dist/lib/constants.js +8 -0
  94. package/dist/lib/constants.js.map +1 -1
  95. package/dist/lib/events.d.ts +34 -1
  96. package/dist/lib/events.js.map +1 -1
  97. package/dist/lib/framework-config.d.ts +6 -0
  98. package/dist/lib/framework-config.js.map +1 -1
  99. package/dist/lib/installer-core.d.ts +14 -1
  100. package/dist/lib/installer-core.js +24 -5
  101. package/dist/lib/installer-core.js.map +1 -1
  102. package/dist/lib/installer-core.types.d.ts +3 -1
  103. package/dist/lib/installer-core.types.js.map +1 -1
  104. package/dist/lib/mcp-clients.d.ts +6 -0
  105. package/dist/lib/mcp-clients.js +13 -0
  106. package/dist/lib/mcp-clients.js.map +1 -1
  107. package/dist/lib/port-detection.js +19 -13
  108. package/dist/lib/port-detection.js.map +1 -1
  109. package/dist/lib/preferences.d.ts +30 -2
  110. package/dist/lib/preferences.js +34 -8
  111. package/dist/lib/preferences.js.map +1 -1
  112. package/dist/lib/run-with-core.js +40 -3
  113. package/dist/lib/run-with-core.js.map +1 -1
  114. package/dist/lib/telemetry-notice.d.ts +5 -5
  115. package/dist/lib/telemetry-notice.js +7 -8
  116. package/dist/lib/telemetry-notice.js.map +1 -1
  117. package/dist/lib/unclaimed-env-provision.js +15 -12
  118. package/dist/lib/unclaimed-env-provision.js.map +1 -1
  119. package/dist/lib/unclaimed-warning.js +4 -3
  120. package/dist/lib/unclaimed-warning.js.map +1 -1
  121. package/dist/lib/validation/security-checks.js +2 -1
  122. package/dist/lib/validation/security-checks.js.map +1 -1
  123. package/dist/lib/validation/validator.js +30 -3
  124. package/dist/lib/validation/validator.js.map +1 -1
  125. package/dist/lib/workos-management.js +26 -19
  126. package/dist/lib/workos-management.js.map +1 -1
  127. package/dist/run.d.ts +1 -0
  128. package/dist/run.js +5 -1
  129. package/dist/run.js.map +1 -1
  130. package/dist/steps/add-or-update-environment-variables.js +10 -10
  131. package/dist/steps/add-or-update-environment-variables.js.map +1 -1
  132. package/dist/steps/run-prettier.js +3 -3
  133. package/dist/steps/run-prettier.js.map +1 -1
  134. package/dist/steps/upload-environment-variables/index.js +15 -3
  135. package/dist/steps/upload-environment-variables/index.js.map +1 -1
  136. package/dist/steps/upload-environment-variables/providers/vercel.js +2 -2
  137. package/dist/steps/upload-environment-variables/providers/vercel.js.map +1 -1
  138. package/dist/utils/box.d.ts +6 -30
  139. package/dist/utils/box.js +8 -95
  140. package/dist/utils/box.js.map +1 -1
  141. package/dist/utils/cli-symbols.d.ts +14 -2
  142. package/dist/utils/cli-symbols.js +12 -0
  143. package/dist/utils/cli-symbols.js.map +1 -1
  144. package/dist/utils/debug.js +3 -3
  145. package/dist/utils/debug.js.map +1 -1
  146. package/dist/utils/environment.js +1 -1
  147. package/dist/utils/environment.js.map +1 -1
  148. package/dist/utils/help-json.js +115 -4
  149. package/dist/utils/help-json.js.map +1 -1
  150. package/dist/utils/package-manager.js +1 -1
  151. package/dist/utils/package-manager.js.map +1 -1
  152. package/dist/utils/recovery-hints.d.ts +5 -0
  153. package/dist/utils/recovery-hints.js +12 -0
  154. package/dist/utils/recovery-hints.js.map +1 -1
  155. package/dist/utils/summary-box.d.ts +8 -1
  156. package/dist/utils/summary-box.js +67 -4
  157. package/dist/utils/summary-box.js.map +1 -1
  158. package/dist/utils/types.d.ts +10 -0
  159. package/dist/utils/types.js.map +1 -1
  160. package/dist/utils/{clack-utils.d.ts → ui-utils.d.ts} +1 -1
  161. package/dist/utils/{clack-utils.js → ui-utils.js} +64 -37
  162. package/dist/utils/ui-utils.js.map +1 -0
  163. package/dist/utils/ui.d.ts +148 -0
  164. package/dist/utils/ui.js +368 -0
  165. package/dist/utils/ui.js.map +1 -0
  166. package/package.json +5 -13
  167. package/dist/check-coverage.ts +0 -237
  168. package/dist/emulate/core/id.d.ts +0 -48
  169. package/dist/emulate/core/id.js +0 -73
  170. package/dist/emulate/core/id.js.map +0 -1
  171. package/dist/emulate/core/index.d.ts +0 -8
  172. package/dist/emulate/core/index.js +0 -8
  173. package/dist/emulate/core/index.js.map +0 -1
  174. package/dist/emulate/core/jwt.d.ts +0 -28
  175. package/dist/emulate/core/jwt.js +0 -78
  176. package/dist/emulate/core/jwt.js.map +0 -1
  177. package/dist/emulate/core/middleware/auth.d.ts +0 -15
  178. package/dist/emulate/core/middleware/auth.js +0 -17
  179. package/dist/emulate/core/middleware/auth.js.map +0 -1
  180. package/dist/emulate/core/middleware/error-handler.d.ts +0 -22
  181. package/dist/emulate/core/middleware/error-handler.js +0 -72
  182. package/dist/emulate/core/middleware/error-handler.js.map +0 -1
  183. package/dist/emulate/core/pagination.d.ts +0 -27
  184. package/dist/emulate/core/pagination.js +0 -43
  185. package/dist/emulate/core/pagination.js.map +0 -1
  186. package/dist/emulate/core/plugin.d.ts +0 -15
  187. package/dist/emulate/core/plugin.js +0 -2
  188. package/dist/emulate/core/plugin.js.map +0 -1
  189. package/dist/emulate/core/server.d.ts +0 -17
  190. package/dist/emulate/core/server.js +0 -90
  191. package/dist/emulate/core/server.js.map +0 -1
  192. package/dist/emulate/core/store.d.ts +0 -44
  193. package/dist/emulate/core/store.js +0 -169
  194. package/dist/emulate/core/store.js.map +0 -1
  195. package/dist/emulate/index.d.ts +0 -25
  196. package/dist/emulate/index.js +0 -47
  197. package/dist/emulate/index.js.map +0 -1
  198. package/dist/emulate/workos/constants.d.ts +0 -56
  199. package/dist/emulate/workos/constants.js +0 -56
  200. package/dist/emulate/workos/constants.js.map +0 -1
  201. package/dist/emulate/workos/entities.d.ts +0 -360
  202. package/dist/emulate/workos/entities.js +0 -2
  203. package/dist/emulate/workos/entities.js.map +0 -1
  204. package/dist/emulate/workos/event-bus.d.ts +0 -17
  205. package/dist/emulate/workos/event-bus.js +0 -70
  206. package/dist/emulate/workos/event-bus.js.map +0 -1
  207. package/dist/emulate/workos/helpers.d.ts +0 -72
  208. package/dist/emulate/workos/helpers.js +0 -211
  209. package/dist/emulate/workos/helpers.js.map +0 -1
  210. package/dist/emulate/workos/index.d.ts +0 -93
  211. package/dist/emulate/workos/index.js +0 -326
  212. package/dist/emulate/workos/index.js.map +0 -1
  213. package/dist/emulate/workos/role-helpers.d.ts +0 -21
  214. package/dist/emulate/workos/role-helpers.js +0 -130
  215. package/dist/emulate/workos/role-helpers.js.map +0 -1
  216. package/dist/emulate/workos/routes/api-keys.d.ts +0 -2
  217. package/dist/emulate/workos/routes/api-keys.js +0 -32
  218. package/dist/emulate/workos/routes/api-keys.js.map +0 -1
  219. package/dist/emulate/workos/routes/audit-logs.d.ts +0 -2
  220. package/dist/emulate/workos/routes/audit-logs.js +0 -104
  221. package/dist/emulate/workos/routes/audit-logs.js.map +0 -1
  222. package/dist/emulate/workos/routes/auth-challenges.d.ts +0 -2
  223. package/dist/emulate/workos/routes/auth-challenges.js +0 -51
  224. package/dist/emulate/workos/routes/auth-challenges.js.map +0 -1
  225. package/dist/emulate/workos/routes/auth-factors.d.ts +0 -2
  226. package/dist/emulate/workos/routes/auth-factors.js +0 -51
  227. package/dist/emulate/workos/routes/auth-factors.js.map +0 -1
  228. package/dist/emulate/workos/routes/auth.d.ts +0 -2
  229. package/dist/emulate/workos/routes/auth.js +0 -350
  230. package/dist/emulate/workos/routes/auth.js.map +0 -1
  231. package/dist/emulate/workos/routes/authorization-checks.d.ts +0 -10
  232. package/dist/emulate/workos/routes/authorization-checks.js +0 -123
  233. package/dist/emulate/workos/routes/authorization-checks.js.map +0 -1
  234. package/dist/emulate/workos/routes/authorization-org-roles.d.ts +0 -2
  235. package/dist/emulate/workos/routes/authorization-org-roles.js +0 -64
  236. package/dist/emulate/workos/routes/authorization-org-roles.js.map +0 -1
  237. package/dist/emulate/workos/routes/authorization-permissions.d.ts +0 -2
  238. package/dist/emulate/workos/routes/authorization-permissions.js +0 -67
  239. package/dist/emulate/workos/routes/authorization-permissions.js.map +0 -1
  240. package/dist/emulate/workos/routes/authorization-resources.d.ts +0 -2
  241. package/dist/emulate/workos/routes/authorization-resources.js +0 -117
  242. package/dist/emulate/workos/routes/authorization-resources.js.map +0 -1
  243. package/dist/emulate/workos/routes/authorization-roles.d.ts +0 -2
  244. package/dist/emulate/workos/routes/authorization-roles.js +0 -13
  245. package/dist/emulate/workos/routes/authorization-roles.js.map +0 -1
  246. package/dist/emulate/workos/routes/config.d.ts +0 -2
  247. package/dist/emulate/workos/routes/config.js +0 -57
  248. package/dist/emulate/workos/routes/config.js.map +0 -1
  249. package/dist/emulate/workos/routes/connect.d.ts +0 -2
  250. package/dist/emulate/workos/routes/connect.js +0 -65
  251. package/dist/emulate/workos/routes/connect.js.map +0 -1
  252. package/dist/emulate/workos/routes/connections.d.ts +0 -2
  253. package/dist/emulate/workos/routes/connections.js +0 -73
  254. package/dist/emulate/workos/routes/connections.js.map +0 -1
  255. package/dist/emulate/workos/routes/data-integrations.d.ts +0 -2
  256. package/dist/emulate/workos/routes/data-integrations.js +0 -55
  257. package/dist/emulate/workos/routes/data-integrations.js.map +0 -1
  258. package/dist/emulate/workos/routes/directories.d.ts +0 -2
  259. package/dist/emulate/workos/routes/directories.js +0 -90
  260. package/dist/emulate/workos/routes/directories.js.map +0 -1
  261. package/dist/emulate/workos/routes/email-verification.d.ts +0 -2
  262. package/dist/emulate/workos/routes/email-verification.js +0 -49
  263. package/dist/emulate/workos/routes/email-verification.js.map +0 -1
  264. package/dist/emulate/workos/routes/events.d.ts +0 -2
  265. package/dist/emulate/workos/routes/events.js +0 -18
  266. package/dist/emulate/workos/routes/events.js.map +0 -1
  267. package/dist/emulate/workos/routes/feature-flags.d.ts +0 -2
  268. package/dist/emulate/workos/routes/feature-flags.js +0 -103
  269. package/dist/emulate/workos/routes/feature-flags.js.map +0 -1
  270. package/dist/emulate/workos/routes/invitations.d.ts +0 -2
  271. package/dist/emulate/workos/routes/invitations.js +0 -122
  272. package/dist/emulate/workos/routes/invitations.js.map +0 -1
  273. package/dist/emulate/workos/routes/legacy-mfa.d.ts +0 -2
  274. package/dist/emulate/workos/routes/legacy-mfa.js +0 -75
  275. package/dist/emulate/workos/routes/legacy-mfa.js.map +0 -1
  276. package/dist/emulate/workos/routes/magic-auth.d.ts +0 -2
  277. package/dist/emulate/workos/routes/magic-auth.js +0 -32
  278. package/dist/emulate/workos/routes/magic-auth.js.map +0 -1
  279. package/dist/emulate/workos/routes/memberships.d.ts +0 -2
  280. package/dist/emulate/workos/routes/memberships.js +0 -114
  281. package/dist/emulate/workos/routes/memberships.js.map +0 -1
  282. package/dist/emulate/workos/routes/organization-domains.d.ts +0 -2
  283. package/dist/emulate/workos/routes/organization-domains.js +0 -58
  284. package/dist/emulate/workos/routes/organization-domains.js.map +0 -1
  285. package/dist/emulate/workos/routes/organizations.d.ts +0 -2
  286. package/dist/emulate/workos/routes/organizations.js +0 -131
  287. package/dist/emulate/workos/routes/organizations.js.map +0 -1
  288. package/dist/emulate/workos/routes/password-reset.d.ts +0 -2
  289. package/dist/emulate/workos/routes/password-reset.js +0 -61
  290. package/dist/emulate/workos/routes/password-reset.js.map +0 -1
  291. package/dist/emulate/workos/routes/pipes.d.ts +0 -2
  292. package/dist/emulate/workos/routes/pipes.js +0 -82
  293. package/dist/emulate/workos/routes/pipes.js.map +0 -1
  294. package/dist/emulate/workos/routes/portal.d.ts +0 -2
  295. package/dist/emulate/workos/routes/portal.js +0 -18
  296. package/dist/emulate/workos/routes/portal.js.map +0 -1
  297. package/dist/emulate/workos/routes/radar.d.ts +0 -2
  298. package/dist/emulate/workos/routes/radar.js +0 -41
  299. package/dist/emulate/workos/routes/radar.js.map +0 -1
  300. package/dist/emulate/workos/routes/sessions.d.ts +0 -2
  301. package/dist/emulate/workos/routes/sessions.js +0 -51
  302. package/dist/emulate/workos/routes/sessions.js.map +0 -1
  303. package/dist/emulate/workos/routes/sso.d.ts +0 -2
  304. package/dist/emulate/workos/routes/sso.js +0 -161
  305. package/dist/emulate/workos/routes/sso.js.map +0 -1
  306. package/dist/emulate/workos/routes/user-features.d.ts +0 -2
  307. package/dist/emulate/workos/routes/user-features.js +0 -50
  308. package/dist/emulate/workos/routes/user-features.js.map +0 -1
  309. package/dist/emulate/workos/routes/users.d.ts +0 -2
  310. package/dist/emulate/workos/routes/users.js +0 -129
  311. package/dist/emulate/workos/routes/users.js.map +0 -1
  312. package/dist/emulate/workos/routes/webhook-endpoints.d.ts +0 -2
  313. package/dist/emulate/workos/routes/webhook-endpoints.js +0 -67
  314. package/dist/emulate/workos/routes/webhook-endpoints.js.map +0 -1
  315. package/dist/emulate/workos/routes/widgets.d.ts +0 -2
  316. package/dist/emulate/workos/routes/widgets.js +0 -27
  317. package/dist/emulate/workos/routes/widgets.js.map +0 -1
  318. package/dist/emulate/workos/store.d.ts +0 -48
  319. package/dist/emulate/workos/store.js +0 -102
  320. package/dist/emulate/workos/store.js.map +0 -1
  321. package/dist/emulate/workos/webhook-signer.d.ts +0 -1
  322. package/dist/emulate/workos/webhook-signer.js +0 -8
  323. package/dist/emulate/workos/webhook-signer.js.map +0 -1
  324. package/dist/gen-routes-lib.spec.ts +0 -659
  325. package/dist/gen-routes-lib.ts +0 -647
  326. package/dist/gen-routes.ts +0 -96
  327. package/dist/lib/mcp-notice.d.ts +0 -72
  328. package/dist/lib/mcp-notice.js +0 -275
  329. package/dist/lib/mcp-notice.js.map +0 -1
  330. package/dist/utils/clack-utils.js.map +0 -1
  331. package/dist/utils/clack.d.ts +0 -5
  332. package/dist/utils/clack.js +0 -34
  333. package/dist/utils/clack.js.map +0 -1
@@ -1,82 +1,91 @@
1
1
  import open from 'open';
2
2
  import chalk from 'chalk';
3
- import clack from '../utils/clack.js';
3
+ import ui from '../utils/ui.js';
4
4
  import { saveCredentials, getCredentials, getAccessToken, isTokenExpired, updateTokens } from '../lib/credentials.js';
5
5
  import { getCliAuthClientId, getAuthkitDomain } from '../lib/settings.js';
6
6
  import { refreshAccessToken } from '../lib/token-refresh-client.js';
7
7
  import { logInfo, logError } from '../utils/debug.js';
8
- import { fetchStagingCredentials } from '../lib/staging-api.js';
9
- import { getConfig, saveConfig } from '../lib/config-store.js';
8
+ import { fetchStagingCredentials, StagingApiError } from '../lib/staging-api.js';
9
+ import { analytics } from '../utils/analytics.js';
10
+ import { getConfig, saveConfig, getActiveEnvironment, setActiveEnvironment, freshEnvKey } from '../lib/config-store.js';
10
11
  import { formatWorkOSCommand } from '../utils/command-invocation.js';
11
- import { autoInstallSkills } from './install-skill.js';
12
- import { isJsonMode } from '../utils/output.js';
13
- import { isAgentMode, isCiMode } from '../utils/interaction-mode.js';
12
+ import { maybeRunSetupAfter } from './setup.js';
13
+ import { isJsonMode, outputJson } from '../utils/output.js';
14
+ import { isAgentMode, isCiMode, isPromptAllowed } from '../utils/interaction-mode.js';
14
15
  import { ExitCode, exitWithAuthRequired, exitWithCode } from '../utils/exit-codes.js';
15
16
  import { requestDeviceCode, pollForToken, DeviceAuthTimeoutError } from '../lib/device-auth.js';
16
17
  import { observeHostFailure } from '../lib/host-probe.js';
17
18
  /**
18
- * Best-effort skill install after a successful auth-login.
19
+ * Does the just-authenticated account differ from the account that owns `prior`?
19
20
  *
20
- * Mirrors the install.ts hook copy, but wraps `autoInstallSkills` in its own
21
- * try/catch AND a 30s timeout so a skill install hang (e.g. blocked filesystem
22
- * call) never blocks login completion. Login already succeeded by the time
23
- * this runs — the user having a working session is the contract that must hold.
24
- *
25
- * Extracted from runLogin so it can be unit-tested without standing up the
26
- * device-auth polling loop.
21
+ * Email comparison wins when both sides have it (human-readable, survives a
22
+ * clientId reissue); otherwise fall back to clientId. When neither is available
23
+ * we cannot tell return false and let the always-on "Now using" line protect
24
+ * the user.
27
25
  */
28
- export const SKILL_INSTALL_TIMEOUT_MS = 30 * 1000;
29
- export async function installSkillsAfterLogin() {
30
- let timeoutHandle;
31
- try {
32
- const timeout = new Promise((resolve) => {
33
- timeoutHandle = setTimeout(() => resolve(null), SKILL_INSTALL_TIMEOUT_MS);
34
- // Don't keep the event loop alive on this timer — process should exit
35
- // immediately if everything else has resolved.
36
- timeoutHandle.unref?.();
37
- });
38
- const result = await Promise.race([autoInstallSkills(), timeout]);
39
- if (result && !isJsonMode()) {
40
- const skillWord = result.skills.length === 1 ? 'skill' : 'skills';
41
- clack.log.info(`Installed ${result.skills.length} WorkOS ${skillWord} for ${result.agents.join(', ')}.`);
42
- }
43
- }
44
- catch {
45
- // Skill install must never fail login.
46
- }
47
- finally {
48
- if (timeoutHandle)
49
- clearTimeout(timeoutHandle);
50
- }
26
+ function isMismatch(prior, account, staging) {
27
+ if (!prior)
28
+ return false;
29
+ if (prior.ownerEmail && account.email)
30
+ return prior.ownerEmail !== account.email;
31
+ if (prior.clientId)
32
+ return prior.clientId !== staging.clientId;
33
+ return false;
51
34
  }
52
35
  /**
53
36
  * Auto-provision a staging environment after login.
54
37
  *
55
- * Fetches staging credentials using the access token, then saves them
56
- * as a "staging" environment in the config store. Non-fatal — logs a
57
- * hint on failure instead of throwing.
38
+ * Fetches staging credentials for the just-authenticated account and stores
39
+ * them. On a detected cross-account mismatch, the new account's Staging is
40
+ * written under a DISTINCT key rather than clobbering the active slot, and the
41
+ * active pointer is left alone — only a login onto an empty config auto-assigns
42
+ * the active env. Non-fatal — logs a hint on failure instead of throwing.
58
43
  */
59
- export async function provisionStagingEnvironment(accessToken) {
44
+ export async function provisionStagingEnvironment(accessToken, account) {
60
45
  try {
61
46
  const staging = await fetchStagingCredentials(accessToken);
62
47
  const config = getConfig() ?? { environments: {} };
63
- const isFirst = Object.keys(config.environments).length === 0;
64
- config.environments['staging'] = {
65
- name: 'staging',
48
+ const priorName = config.activeEnvironment;
49
+ const prior = priorName ? config.environments[priorName] : undefined; // capture BEFORE write
50
+ const mismatch = isMismatch(prior, account, staging);
51
+ // Never overwrite a DIFFERENT account's 'staging' slot in place.
52
+ const stagingSlot = config.environments['staging'];
53
+ const slotMismatch = isMismatch(stagingSlot, account, staging);
54
+ const key = slotMismatch ? freshEnvKey(config, 'staging') : 'staging';
55
+ config.environments[key] = {
56
+ name: key,
66
57
  type: 'sandbox',
67
58
  apiKey: staging.apiKey,
68
59
  clientId: staging.clientId,
60
+ ...(account.email && { ownerEmail: account.email }),
61
+ ownerUserId: account.userId,
69
62
  };
70
- if (isFirst || !config.activeEnvironment) {
71
- config.activeEnvironment = 'staging';
63
+ // Only auto-assign active when there is NO valid prior active env.
64
+ if (!prior) {
65
+ config.activeEnvironment = key;
72
66
  }
73
67
  saveConfig(config);
74
- logInfo('[login] Staging environment auto-provisioned');
75
- return true;
68
+ logInfo('[login] Staging environment provisioned');
69
+ return {
70
+ provisioned: true,
71
+ activeEnvironment: config.activeEnvironment,
72
+ envName: key,
73
+ mismatch,
74
+ priorEnvName: priorName,
75
+ priorAccount: prior ? { email: prior.ownerEmail, clientId: prior.clientId } : undefined,
76
+ };
76
77
  }
77
78
  catch (error) {
78
- logError('[login] Failed to auto-provision staging environment:', error instanceof Error ? error.message : error);
79
- return false;
79
+ logError('[login] Failed to provision staging environment:', error instanceof Error ? error.message : error);
80
+ // Best-effort, but the failure rate of this onboarding step must be visible:
81
+ // a silent failure here leaves the user with no active environment for every
82
+ // later command, indistinguishable in telemetry from a healthy setup.
83
+ analytics.captureException(error instanceof Error ? error : new Error(String(error)), {
84
+ command: 'auth.login',
85
+ phase: 'provision-staging',
86
+ statusCode: error instanceof StagingApiError ? error.statusCode : undefined,
87
+ });
88
+ return { provisioned: false, mismatch: false };
80
89
  }
81
90
  }
82
91
  export async function runLogin() {
@@ -101,35 +110,44 @@ export async function runLogin() {
101
110
  console.log(chalk.dim(`Run \`${formatWorkOSCommand('auth logout')}\` to log out`));
102
111
  return;
103
112
  }
113
+ // Refresh returned no token — record why before falling through to fresh
114
+ // login. A spike here surfaces token revocation / refresh-endpoint outages
115
+ // that self-heal into a browser login and would otherwise be invisible.
116
+ analytics.capture('token_refresh_failed', { errorType: result.errorType ?? 'unknown' });
104
117
  }
105
- catch {
106
- // Refresh failed, proceed with fresh login
118
+ catch (error) {
119
+ analytics.capture('token_refresh_failed', { errorType: error instanceof Error ? error.name : 'unknown' });
120
+ // Refresh failed, proceed with fresh login.
107
121
  }
108
122
  }
109
123
  if (isCiMode()) {
110
124
  exitWithAuthRequired('Browser authentication is not available in CI mode. Set WORKOS_API_KEY or configure credentials before running in CI.');
111
125
  }
112
126
  const authkitDomain = getAuthkitDomain();
113
- clack.log.step('Starting authentication...');
127
+ ui.log.step('Starting authentication...');
114
128
  let deviceAuth;
115
129
  try {
116
130
  deviceAuth = await requestDeviceCode({ clientId, authkitDomain });
117
131
  }
118
132
  catch (error) {
119
133
  const msg = error instanceof Error ? error.message : String(error);
120
- clack.log.error(`Failed to start authentication: ${msg}`);
134
+ ui.log.error(`Failed to start authentication: ${msg}`);
135
+ analytics.captureException(error instanceof Error ? error : new Error(msg), {
136
+ command: 'auth.login',
137
+ phase: 'device-code',
138
+ });
121
139
  exitWithCode(ExitCode.GENERAL_ERROR);
122
140
  }
123
- clack.log.info(`\nOpen this URL in your browser:\n`);
141
+ ui.log.info(`\nOpen this URL in your browser:\n`);
124
142
  console.log(` ${deviceAuth.verification_uri}`);
125
143
  console.log(`\nEnter code: ${deviceAuth.user_code}\n`);
126
144
  try {
127
145
  await open(deviceAuth.verification_uri_complete, { wait: false });
128
146
  if (isAgentMode()) {
129
- clack.log.info('Browser launch attempted. If it did not open on the host, use the manual URL and code above.');
147
+ ui.log.info('Browser launch attempted. If it did not open on the host, use the manual URL and code above.');
130
148
  }
131
149
  else {
132
- clack.log.info('Browser opened automatically');
150
+ ui.log.info('Browser opened automatically');
133
151
  }
134
152
  }
135
153
  catch (error) {
@@ -138,9 +156,9 @@ export async function runLogin() {
138
156
  target: deviceAuth.verification_uri_complete,
139
157
  label: 'auth login browser',
140
158
  });
141
- clack.log.info('Could not open browser — open the URL above manually.');
159
+ ui.log.info('Could not open browser — open the URL above manually.');
142
160
  }
143
- const spinner = clack.spinner();
161
+ const spinner = ui.spinner();
144
162
  spinner.start('Waiting for authentication...');
145
163
  try {
146
164
  const result = await pollForToken(deviceAuth.device_code, {
@@ -157,27 +175,64 @@ export async function runLogin() {
157
175
  refreshToken: result.refreshToken,
158
176
  });
159
177
  spinner.stop('Authentication successful!');
160
- clack.log.success(`Logged in as ${result.email || result.userId}`);
161
- clack.log.info(`Token expires in ${expiresInSec} seconds`);
162
- const provisioned = await provisionStagingEnvironment(result.accessToken);
163
- if (provisioned) {
164
- clack.log.success('Staging environment configured automatically');
178
+ ui.log.success(`Logged in as ${result.email || result.userId}`);
179
+ ui.log.info(`Token expires in ${expiresInSec} seconds`);
180
+ const account = { email: result.email, userId: result.userId };
181
+ const provision = await provisionStagingEnvironment(result.accessToken, account);
182
+ if (isJsonMode()) {
183
+ outputJson({
184
+ status: 'ok',
185
+ account: { email: account.email ?? null, userId: account.userId },
186
+ activeEnvironment: provision.activeEnvironment ?? null,
187
+ mismatch: provision.mismatch,
188
+ });
189
+ }
190
+ else if (provision.provisioned) {
191
+ if (provision.mismatch) {
192
+ const priorLabel = provision.priorAccount?.email ?? provision.priorAccount?.clientId ?? provision.priorEnvName;
193
+ if (isPromptAllowed()) {
194
+ const answer = await ui.confirm({
195
+ message: `You were using ${provision.priorEnvName} (${priorLabel}, a different account). Switch active environment to ${account.email ?? account.userId}'s Staging?`,
196
+ initialValue: false, // default: keep current
197
+ });
198
+ if (!ui.isCancel(answer) && answer && provision.envName) {
199
+ setActiveEnvironment(provision.envName);
200
+ }
201
+ }
202
+ else {
203
+ ui.log.warn(`Logged in as ${account.email ?? account.userId}, but the active environment "${provision.priorEnvName}" belongs to a different account (${priorLabel}). Keeping it active. Run \`${formatWorkOSCommand('env switch')}\` to change environments.`);
204
+ }
205
+ }
206
+ const active = getActiveEnvironment();
207
+ if (active) {
208
+ ui.log.success(`Now using: ${active.name} (${active.type}) — ${account.email ?? account.userId}`);
209
+ }
210
+ else {
211
+ ui.log.info(chalk.dim(`Run \`${formatWorkOSCommand('env add')}\` to configure an environment manually`));
212
+ }
165
213
  }
166
214
  else {
167
- clack.log.info(chalk.dim('Run `workos env add` to configure an environment manually'));
215
+ ui.log.info(chalk.dim(`Run \`${formatWorkOSCommand('env add')}\` to configure an environment manually`));
168
216
  }
169
- await installSkillsAfterLogin();
217
+ await maybeRunSetupAfter('login');
170
218
  }
171
219
  catch (error) {
172
- if (error instanceof DeviceAuthTimeoutError) {
173
- spinner.stop('Authentication timed out');
174
- clack.log.error('Authentication timed out. Please try again.');
220
+ const isTimeout = error instanceof DeviceAuthTimeoutError;
221
+ if (isTimeout) {
222
+ spinner.stop('Authentication timed out', 1);
223
+ ui.log.error('Authentication timed out. Please try again.');
175
224
  }
176
225
  else {
177
- spinner.stop('Authentication failed');
226
+ spinner.stop('Authentication failed', 1);
178
227
  const msg = error instanceof Error ? error.message : String(error);
179
- clack.log.error(`Authentication error: ${msg}`);
228
+ ui.log.error(`Authentication error: ${msg}`);
180
229
  }
230
+ // Deliver the real cause to telemetry (the command event alone can't
231
+ // distinguish a timeout from a network/server auth failure).
232
+ analytics.captureException(error instanceof Error ? error : new Error(String(error)), {
233
+ command: 'auth.login',
234
+ phase: isTimeout ? 'timeout' : 'poll',
235
+ });
181
236
  exitWithCode(ExitCode.GENERAL_ERROR);
182
237
  }
183
238
  }
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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","sourcesContent":["import open from 'open';\nimport chalk from 'chalk';\nimport clack from '../utils/clack.js';\nimport { saveCredentials, getCredentials, getAccessToken, isTokenExpired, updateTokens } from '../lib/credentials.js';\nimport { getCliAuthClientId, getAuthkitDomain } from '../lib/settings.js';\nimport { refreshAccessToken } from '../lib/token-refresh-client.js';\nimport { logInfo, logError } from '../utils/debug.js';\nimport { fetchStagingCredentials } from '../lib/staging-api.js';\nimport { getConfig, saveConfig } from '../lib/config-store.js';\nimport type { CliConfig } from '../lib/config-store.js';\nimport { formatWorkOSCommand } from '../utils/command-invocation.js';\nimport { autoInstallSkills } from './install-skill.js';\nimport { isJsonMode } from '../utils/output.js';\nimport { isAgentMode, isCiMode } from '../utils/interaction-mode.js';\nimport { ExitCode, exitWithAuthRequired, exitWithCode } from '../utils/exit-codes.js';\nimport { requestDeviceCode, pollForToken, DeviceAuthTimeoutError } from '../lib/device-auth.js';\nimport { observeHostFailure } from '../lib/host-probe.js';\n\n/**\n * Best-effort skill install after a successful auth-login.\n *\n * Mirrors the install.ts hook copy, but wraps `autoInstallSkills` in its own\n * try/catch AND a 30s timeout so a skill install hang (e.g. blocked filesystem\n * call) never blocks login completion. Login already succeeded by the time\n * this runs — the user having a working session is the contract that must hold.\n *\n * Extracted from runLogin so it can be unit-tested without standing up the\n * device-auth polling loop.\n */\nexport const SKILL_INSTALL_TIMEOUT_MS = 30 * 1000;\n\nexport async function installSkillsAfterLogin(): Promise<void> {\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n try {\n const timeout = new Promise<null>((resolve) => {\n timeoutHandle = setTimeout(() => resolve(null), SKILL_INSTALL_TIMEOUT_MS);\n // Don't keep the event loop alive on this timer — process should exit\n // immediately if everything else has resolved.\n timeoutHandle.unref?.();\n });\n const result = await Promise.race([autoInstallSkills(), timeout]);\n if (result && !isJsonMode()) {\n const skillWord = result.skills.length === 1 ? 'skill' : 'skills';\n clack.log.info(`Installed ${result.skills.length} WorkOS ${skillWord} for ${result.agents.join(', ')}.`);\n }\n } catch {\n // Skill install must never fail login.\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n}\n\n/**\n * Auto-provision a staging environment after login.\n *\n * Fetches staging credentials using the access token, then saves them\n * as a \"staging\" environment in the config store. Non-fatal — logs a\n * hint on failure instead of throwing.\n */\nexport async function provisionStagingEnvironment(accessToken: string): Promise<boolean> {\n try {\n const staging = await fetchStagingCredentials(accessToken);\n\n const config: CliConfig = getConfig() ?? { environments: {} };\n const isFirst = Object.keys(config.environments).length === 0;\n\n config.environments['staging'] = {\n name: 'staging',\n type: 'sandbox',\n apiKey: staging.apiKey,\n clientId: staging.clientId,\n };\n\n if (isFirst || !config.activeEnvironment) {\n config.activeEnvironment = 'staging';\n }\n\n saveConfig(config);\n logInfo('[login] Staging environment auto-provisioned');\n return true;\n } catch (error) {\n logError('[login] Failed to auto-provision staging environment:', error instanceof Error ? error.message : error);\n return false;\n }\n}\n\nexport async function runLogin(): Promise<void> {\n const clientId = getCliAuthClientId();\n\n // Check if already logged in with valid token\n if (getAccessToken()) {\n const creds = getCredentials();\n console.log(chalk.green(`Already logged in as ${creds?.email ?? 'unknown'}`));\n console.log(chalk.dim(`Run \\`${formatWorkOSCommand('auth logout')}\\` to log out`));\n return;\n }\n\n // Try to refresh if we have expired credentials with a refresh token\n const existingCreds = getCredentials();\n if (existingCreds?.refreshToken && isTokenExpired(existingCreds)) {\n try {\n const authkitDomain = getAuthkitDomain();\n const result = await refreshAccessToken(authkitDomain, clientId);\n if (result.accessToken && result.expiresAt) {\n updateTokens(result.accessToken, result.expiresAt, result.refreshToken);\n logInfo('[login] Session refreshed via refresh token');\n console.log(chalk.green(`Already logged in as ${existingCreds.email ?? 'unknown'}`));\n console.log(chalk.dim(`Run \\`${formatWorkOSCommand('auth logout')}\\` to log out`));\n return;\n }\n } catch {\n // Refresh failed, proceed with fresh login\n }\n }\n\n if (isCiMode()) {\n exitWithAuthRequired(\n 'Browser authentication is not available in CI mode. Set WORKOS_API_KEY or configure credentials before running in CI.',\n );\n }\n\n const authkitDomain = getAuthkitDomain();\n\n clack.log.step('Starting authentication...');\n\n let deviceAuth;\n try {\n deviceAuth = await requestDeviceCode({ clientId, authkitDomain });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n clack.log.error(`Failed to start authentication: ${msg}`);\n exitWithCode(ExitCode.GENERAL_ERROR);\n }\n\n clack.log.info(`\\nOpen this URL in your browser:\\n`);\n console.log(` ${deviceAuth.verification_uri}`);\n console.log(`\\nEnter code: ${deviceAuth.user_code}\\n`);\n\n try {\n await open(deviceAuth.verification_uri_complete, { wait: false });\n if (isAgentMode()) {\n clack.log.info('Browser launch attempted. If it did not open on the host, use the manual URL and code above.');\n } else {\n clack.log.info('Browser opened automatically');\n }\n } catch (error) {\n observeHostFailure('browser-launch', error, {\n operation: 'open',\n target: deviceAuth.verification_uri_complete,\n label: 'auth login browser',\n });\n clack.log.info('Could not open browser — open the URL above manually.');\n }\n\n const spinner = clack.spinner();\n spinner.start('Waiting for authentication...');\n\n try {\n const result = await pollForToken(deviceAuth.device_code, {\n clientId,\n authkitDomain,\n interval: deviceAuth.interval,\n });\n\n const expiresInSec = Math.round((result.expiresAt - Date.now()) / 1000);\n\n saveCredentials({\n accessToken: result.accessToken,\n expiresAt: result.expiresAt,\n userId: result.userId,\n email: result.email,\n refreshToken: result.refreshToken,\n });\n\n spinner.stop('Authentication successful!');\n clack.log.success(`Logged in as ${result.email || result.userId}`);\n clack.log.info(`Token expires in ${expiresInSec} seconds`);\n\n const provisioned = await provisionStagingEnvironment(result.accessToken);\n if (provisioned) {\n clack.log.success('Staging environment configured automatically');\n } else {\n clack.log.info(chalk.dim('Run `workos env add` to configure an environment manually'));\n }\n\n await installSkillsAfterLogin();\n } catch (error) {\n if (error instanceof DeviceAuthTimeoutError) {\n spinner.stop('Authentication timed out');\n clack.log.error('Authentication timed out. Please try again.');\n } else {\n spinner.stop('Authentication failed');\n const msg = error instanceof Error ? error.message : String(error);\n clack.log.error(`Authentication error: ${msg}`);\n }\n exitWithCode(ExitCode.GENERAL_ERROR);\n }\n}\n"]}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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","sourcesContent":["import open from 'open';\nimport chalk from 'chalk';\nimport ui from '../utils/ui.js';\nimport { saveCredentials, getCredentials, getAccessToken, isTokenExpired, updateTokens } from '../lib/credentials.js';\nimport { getCliAuthClientId, getAuthkitDomain } from '../lib/settings.js';\nimport { refreshAccessToken } from '../lib/token-refresh-client.js';\nimport { logInfo, logError } from '../utils/debug.js';\nimport { fetchStagingCredentials, StagingApiError } from '../lib/staging-api.js';\nimport { analytics } from '../utils/analytics.js';\nimport { getConfig, saveConfig, getActiveEnvironment, setActiveEnvironment, freshEnvKey } from '../lib/config-store.js';\nimport type { CliConfig, EnvironmentConfig } from '../lib/config-store.js';\nimport { formatWorkOSCommand } from '../utils/command-invocation.js';\nimport { maybeRunSetupAfter } from './setup.js';\nimport { isJsonMode, outputJson } from '../utils/output.js';\nimport { isAgentMode, isCiMode, isPromptAllowed } from '../utils/interaction-mode.js';\nimport { ExitCode, exitWithAuthRequired, exitWithCode } from '../utils/exit-codes.js';\nimport { requestDeviceCode, pollForToken, DeviceAuthTimeoutError } from '../lib/device-auth.js';\nimport { observeHostFailure } from '../lib/host-probe.js';\n\n/**\n * Result of a post-login staging provision. Carries enough context for\n * `runLogin` to detect a cross-account switch and decide how to surface it\n * without ever silently repointing the active environment.\n */\nexport interface StagingProvisionResult {\n provisioned: boolean;\n /** Active env name AFTER provisioning (unchanged unless there was no prior active env). */\n activeEnvironment?: string;\n /** Key the new Staging env was written under ('staging' or a fresh 'staging-N'). */\n envName?: string;\n mismatch: boolean;\n priorEnvName?: string;\n priorAccount?: { email?: string; clientId?: string };\n}\n\n/**\n * Does the just-authenticated account differ from the account that owns `prior`?\n *\n * Email comparison wins when both sides have it (human-readable, survives a\n * clientId reissue); otherwise fall back to clientId. When neither is available\n * we cannot tell — return false and let the always-on \"Now using\" line protect\n * the user.\n */\nfunction isMismatch(\n prior: EnvironmentConfig | undefined,\n account: { email?: string },\n staging: { clientId: string },\n): boolean {\n if (!prior) return false;\n if (prior.ownerEmail && account.email) return prior.ownerEmail !== account.email;\n if (prior.clientId) return prior.clientId !== staging.clientId;\n return false;\n}\n\n/**\n * Auto-provision a staging environment after login.\n *\n * Fetches staging credentials for the just-authenticated account and stores\n * them. On a detected cross-account mismatch, the new account's Staging is\n * written under a DISTINCT key rather than clobbering the active slot, and the\n * active pointer is left alone — only a login onto an empty config auto-assigns\n * the active env. Non-fatal — logs a hint on failure instead of throwing.\n */\nexport async function provisionStagingEnvironment(\n accessToken: string,\n account: { email?: string; userId: string },\n): Promise<StagingProvisionResult> {\n try {\n const staging = await fetchStagingCredentials(accessToken);\n\n const config: CliConfig = getConfig() ?? { environments: {} };\n\n const priorName = config.activeEnvironment;\n const prior = priorName ? config.environments[priorName] : undefined; // capture BEFORE write\n const mismatch = isMismatch(prior, account, staging);\n\n // Never overwrite a DIFFERENT account's 'staging' slot in place.\n const stagingSlot = config.environments['staging'];\n const slotMismatch = isMismatch(stagingSlot, account, staging);\n const key = slotMismatch ? freshEnvKey(config, 'staging') : 'staging';\n\n config.environments[key] = {\n name: key,\n type: 'sandbox',\n apiKey: staging.apiKey,\n clientId: staging.clientId,\n ...(account.email && { ownerEmail: account.email }),\n ownerUserId: account.userId,\n };\n\n // Only auto-assign active when there is NO valid prior active env.\n if (!prior) {\n config.activeEnvironment = key;\n }\n\n saveConfig(config);\n logInfo('[login] Staging environment provisioned');\n\n return {\n provisioned: true,\n activeEnvironment: config.activeEnvironment,\n envName: key,\n mismatch,\n priorEnvName: priorName,\n priorAccount: prior ? { email: prior.ownerEmail, clientId: prior.clientId } : undefined,\n };\n } catch (error) {\n logError('[login] Failed to provision staging environment:', error instanceof Error ? error.message : error);\n // Best-effort, but the failure rate of this onboarding step must be visible:\n // a silent failure here leaves the user with no active environment for every\n // later command, indistinguishable in telemetry from a healthy setup.\n analytics.captureException(error instanceof Error ? error : new Error(String(error)), {\n command: 'auth.login',\n phase: 'provision-staging',\n statusCode: error instanceof StagingApiError ? error.statusCode : undefined,\n });\n return { provisioned: false, mismatch: false };\n }\n}\n\nexport async function runLogin(): Promise<void> {\n const clientId = getCliAuthClientId();\n\n // Check if already logged in with valid token\n if (getAccessToken()) {\n const creds = getCredentials();\n console.log(chalk.green(`Already logged in as ${creds?.email ?? 'unknown'}`));\n console.log(chalk.dim(`Run \\`${formatWorkOSCommand('auth logout')}\\` to log out`));\n return;\n }\n\n // Try to refresh if we have expired credentials with a refresh token\n const existingCreds = getCredentials();\n if (existingCreds?.refreshToken && isTokenExpired(existingCreds)) {\n try {\n const authkitDomain = getAuthkitDomain();\n const result = await refreshAccessToken(authkitDomain, clientId);\n if (result.accessToken && result.expiresAt) {\n updateTokens(result.accessToken, result.expiresAt, result.refreshToken);\n logInfo('[login] Session refreshed via refresh token');\n console.log(chalk.green(`Already logged in as ${existingCreds.email ?? 'unknown'}`));\n console.log(chalk.dim(`Run \\`${formatWorkOSCommand('auth logout')}\\` to log out`));\n return;\n }\n // Refresh returned no token — record why before falling through to fresh\n // login. A spike here surfaces token revocation / refresh-endpoint outages\n // that self-heal into a browser login and would otherwise be invisible.\n analytics.capture('token_refresh_failed', { errorType: result.errorType ?? 'unknown' });\n } catch (error) {\n analytics.capture('token_refresh_failed', { errorType: error instanceof Error ? error.name : 'unknown' });\n // Refresh failed, proceed with fresh login.\n }\n }\n\n if (isCiMode()) {\n exitWithAuthRequired(\n 'Browser authentication is not available in CI mode. Set WORKOS_API_KEY or configure credentials before running in CI.',\n );\n }\n\n const authkitDomain = getAuthkitDomain();\n\n ui.log.step('Starting authentication...');\n\n let deviceAuth;\n try {\n deviceAuth = await requestDeviceCode({ clientId, authkitDomain });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n ui.log.error(`Failed to start authentication: ${msg}`);\n analytics.captureException(error instanceof Error ? error : new Error(msg), {\n command: 'auth.login',\n phase: 'device-code',\n });\n exitWithCode(ExitCode.GENERAL_ERROR);\n }\n\n ui.log.info(`\\nOpen this URL in your browser:\\n`);\n console.log(` ${deviceAuth.verification_uri}`);\n console.log(`\\nEnter code: ${deviceAuth.user_code}\\n`);\n\n try {\n await open(deviceAuth.verification_uri_complete, { wait: false });\n if (isAgentMode()) {\n ui.log.info('Browser launch attempted. If it did not open on the host, use the manual URL and code above.');\n } else {\n ui.log.info('Browser opened automatically');\n }\n } catch (error) {\n observeHostFailure('browser-launch', error, {\n operation: 'open',\n target: deviceAuth.verification_uri_complete,\n label: 'auth login browser',\n });\n ui.log.info('Could not open browser — open the URL above manually.');\n }\n\n const spinner = ui.spinner();\n spinner.start('Waiting for authentication...');\n\n try {\n const result = await pollForToken(deviceAuth.device_code, {\n clientId,\n authkitDomain,\n interval: deviceAuth.interval,\n });\n\n const expiresInSec = Math.round((result.expiresAt - Date.now()) / 1000);\n\n saveCredentials({\n accessToken: result.accessToken,\n expiresAt: result.expiresAt,\n userId: result.userId,\n email: result.email,\n refreshToken: result.refreshToken,\n });\n\n spinner.stop('Authentication successful!');\n ui.log.success(`Logged in as ${result.email || result.userId}`);\n ui.log.info(`Token expires in ${expiresInSec} seconds`);\n\n const account = { email: result.email, userId: result.userId };\n const provision = await provisionStagingEnvironment(result.accessToken, account);\n\n if (isJsonMode()) {\n outputJson({\n status: 'ok',\n account: { email: account.email ?? null, userId: account.userId },\n activeEnvironment: provision.activeEnvironment ?? null,\n mismatch: provision.mismatch,\n });\n } else if (provision.provisioned) {\n if (provision.mismatch) {\n const priorLabel = provision.priorAccount?.email ?? provision.priorAccount?.clientId ?? provision.priorEnvName;\n if (isPromptAllowed()) {\n const answer = await ui.confirm({\n message: `You were using ${provision.priorEnvName} (${priorLabel}, a different account). Switch active environment to ${account.email ?? account.userId}'s Staging?`,\n initialValue: false, // default: keep current\n });\n if (!ui.isCancel(answer) && answer && provision.envName) {\n setActiveEnvironment(provision.envName);\n }\n } else {\n ui.log.warn(\n `Logged in as ${account.email ?? account.userId}, but the active environment \"${provision.priorEnvName}\" belongs to a different account (${priorLabel}). Keeping it active. Run \\`${formatWorkOSCommand('env switch')}\\` to change environments.`,\n );\n }\n }\n const active = getActiveEnvironment();\n if (active) {\n ui.log.success(`Now using: ${active.name} (${active.type}) — ${account.email ?? account.userId}`);\n } else {\n ui.log.info(chalk.dim(`Run \\`${formatWorkOSCommand('env add')}\\` to configure an environment manually`));\n }\n } else {\n ui.log.info(chalk.dim(`Run \\`${formatWorkOSCommand('env add')}\\` to configure an environment manually`));\n }\n\n await maybeRunSetupAfter('login');\n } catch (error) {\n const isTimeout = error instanceof DeviceAuthTimeoutError;\n if (isTimeout) {\n spinner.stop('Authentication timed out', 1);\n ui.log.error('Authentication timed out. Please try again.');\n } else {\n spinner.stop('Authentication failed', 1);\n const msg = error instanceof Error ? error.message : String(error);\n ui.log.error(`Authentication error: ${msg}`);\n }\n // Deliver the real cause to telemetry (the command event alone can't\n // distinguish a timeout from a network/server auth failure).\n analytics.captureException(error instanceof Error ? error : new Error(String(error)), {\n command: 'auth.login',\n phase: isTimeout ? 'timeout' : 'poll',\n });\n exitWithCode(ExitCode.GENERAL_ERROR);\n }\n}\n"]}
@@ -1,17 +1,17 @@
1
- import clack from '../utils/clack.js';
1
+ import ui from '../utils/ui.js';
2
2
  import { clearCredentials, hasCredentials, getCredentials } from '../lib/credentials.js';
3
3
  export async function runLogout() {
4
4
  if (!hasCredentials()) {
5
- clack.log.info('Not logged in');
5
+ ui.log.info('Not logged in');
6
6
  return;
7
7
  }
8
8
  const creds = getCredentials();
9
9
  clearCredentials();
10
10
  if (creds?.email) {
11
- clack.log.success(`Logged out from ${creds.email}`);
11
+ ui.log.success(`Logged out from ${creds.email}`);
12
12
  }
13
13
  else {
14
- clack.log.success('Logged out successfully');
14
+ ui.log.success('Logged out successfully');
15
15
  }
16
16
  }
17
17
  //# sourceMappingURL=logout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,mBAAmB,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEzF,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QACtB,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAChC,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;IAC/B,gBAAgB,EAAE,CAAC;IAEnB,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;QACjB,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,mBAAmB,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC","sourcesContent":["import clack from '../utils/clack.js';\nimport { clearCredentials, hasCredentials, getCredentials } from '../lib/credentials.js';\n\nexport async function runLogout(): Promise<void> {\n if (!hasCredentials()) {\n clack.log.info('Not logged in');\n return;\n }\n\n const creds = getCredentials();\n clearCredentials();\n\n if (creds?.email) {\n clack.log.success(`Logged out from ${creds.email}`);\n } else {\n clack.log.success('Logged out successfully');\n }\n}\n"]}
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEzF,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QACtB,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC7B,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;IAC/B,gBAAgB,EAAE,CAAC;IAEnB,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;QACjB,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,mBAAmB,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACnD,CAAC;SAAM,CAAC;QACN,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC","sourcesContent":["import ui from '../utils/ui.js';\nimport { clearCredentials, hasCredentials, getCredentials } from '../lib/credentials.js';\n\nexport async function runLogout(): Promise<void> {\n if (!hasCredentials()) {\n ui.log.info('Not logged in');\n return;\n }\n\n const creds = getCredentials();\n clearCredentials();\n\n if (creds?.email) {\n ui.log.success(`Logged out from ${creds.email}`);\n } else {\n ui.log.success('Logged out successfully');\n }\n}\n"]}
@@ -1,16 +1,7 @@
1
- import clack from '../utils/clack.js';
1
+ import ui from '../utils/ui.js';
2
2
  import { outputSuccess, outputJson, outputTable, exitWithError, isJsonMode } from '../utils/output.js';
3
3
  import { ExitCode, exitWithCode } from '../utils/exit-codes.js';
4
- import { createMcpClients, detectMcpClients, MCP_AGENT_KEYS, } from '../lib/mcp-clients.js';
5
- /** Human phrasing for each outcome (JSON mode emits the raw `outcome` value). */
6
- const OUTCOME_LABEL = {
7
- installed: 'installed',
8
- 'already-installed': 'already installed',
9
- removed: 'removed',
10
- 'not-installed': 'not installed',
11
- skipped: 'skipped',
12
- failed: 'failed',
13
- };
4
+ import { createMcpClients, detectMcpClients, MCP_AGENT_KEYS, MCP_OUTCOME_LABELS, } from '../lib/mcp-clients.js';
14
5
  /**
15
6
  * Validate `--agent` values against known keys. Unknown values exit with a
16
7
  * structured `unknown_agent` error. Returns undefined (no filter) when none
@@ -34,7 +25,7 @@ function reportNoAgents() {
34
25
  outputSuccess('No supported coding agents detected', { agents: [] });
35
26
  }
36
27
  else {
37
- clack.log.info('No supported coding agents detected (looked for Claude Code, Codex, Cursor).');
28
+ ui.log.info('No supported coding agents detected (looked for Claude Code, Codex, Cursor).');
38
29
  }
39
30
  }
40
31
  /**
@@ -47,15 +38,15 @@ function reportResults(message, results) {
47
38
  }
48
39
  else {
49
40
  for (const r of results) {
50
- const line = `${r.displayName}: ${OUTCOME_LABEL[r.outcome]}`;
41
+ const line = `${r.displayName}: ${MCP_OUTCOME_LABELS[r.outcome]}`;
51
42
  if (r.outcome === 'failed') {
52
- clack.log.error(r.error ? `${line} — ${r.error}` : line);
43
+ ui.log.error(r.error ? `${line} — ${r.error}` : line);
53
44
  }
54
45
  else if (r.outcome === 'installed' || r.outcome === 'removed' || r.outcome === 'already-installed') {
55
- clack.log.success(line);
46
+ ui.log.success(line);
56
47
  }
57
48
  else {
58
- clack.log.info(line);
49
+ ui.log.info(line);
59
50
  }
60
51
  }
61
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"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","sourcesContent":["import clack from '../utils/clack.js';\nimport { outputSuccess, outputJson, outputTable, exitWithError, isJsonMode } from '../utils/output.js';\nimport { ExitCode, exitWithCode } from '../utils/exit-codes.js';\nimport {\n createMcpClients,\n detectMcpClients,\n MCP_AGENT_KEYS,\n type McpAgentKey,\n type McpClientResult,\n} from '../lib/mcp-clients.js';\n\n/**\n * `workos mcp install | remove | status` handlers.\n *\n * Thin callers over `lib/mcp-clients.ts`: detect the clients, run the\n * operation, and format the per-agent matrix in both output modes. No prompts\n * (non-TTY-safe by construction) and no auth guard — the WorkOS MCP server is\n * secret-free, so configuring it never needs an API key.\n */\n\nexport interface McpCommandOptions {\n agent?: string[];\n}\n\n/** Human phrasing for each outcome (JSON mode emits the raw `outcome` value). */\nconst OUTCOME_LABEL: Record<McpClientResult['outcome'], string> = {\n installed: 'installed',\n 'already-installed': 'already installed',\n removed: 'removed',\n 'not-installed': 'not installed',\n skipped: 'skipped',\n failed: 'failed',\n};\n\n/**\n * Validate `--agent` values against known keys. Unknown values exit with a\n * structured `unknown_agent` error. Returns undefined (no filter) when none\n * were passed, so callers act on all detected agents.\n */\nfunction resolveAgentFilter(agent?: string[]): McpAgentKey[] | undefined {\n if (!agent || agent.length === 0) return undefined;\n const unknown = agent.filter((a) => !MCP_AGENT_KEYS.includes(a as McpAgentKey));\n if (unknown.length > 0) {\n exitWithError({\n code: 'unknown_agent',\n message: `Unknown agent(s): ${unknown.join(', ')}. Supported: ${MCP_AGENT_KEYS.join(', ')}.`,\n });\n }\n return agent as McpAgentKey[];\n}\n\n/** Zero detected agents: same message + exit 0 for both install and remove. */\nfunction reportNoAgents(): void {\n if (isJsonMode()) {\n outputSuccess('No supported coding agents detected', { agents: [] });\n } else {\n clack.log.info('No supported coding agents detected (looked for Claude Code, Codex, Cursor).');\n }\n}\n\n/**\n * Emit the per-agent matrix, then exit non-zero if any agent failed. The full\n * matrix is always emitted first so partial success is still fully reported.\n */\nfunction reportResults(message: string, results: McpClientResult[]): void {\n if (isJsonMode()) {\n outputSuccess(message, { agents: results });\n } else {\n for (const r of results) {\n const line = `${r.displayName}: ${OUTCOME_LABEL[r.outcome]}`;\n if (r.outcome === 'failed') {\n clack.log.error(r.error ? `${line} — ${r.error}` : line);\n } else if (r.outcome === 'installed' || r.outcome === 'removed' || r.outcome === 'already-installed') {\n clack.log.success(line);\n } else {\n clack.log.info(line);\n }\n }\n }\n\n if (results.some((r) => r.outcome === 'failed')) {\n exitWithCode(ExitCode.GENERAL_ERROR);\n }\n}\n\nexport async function runMcpInstall(options: McpCommandOptions = {}): Promise<void> {\n const filter = resolveAgentFilter(options.agent);\n const clients = await detectMcpClients(filter);\n if (clients.length === 0) {\n reportNoAgents();\n return;\n }\n const results: McpClientResult[] = [];\n for (const client of clients) {\n results.push(await client.add());\n }\n reportResults('Configured WorkOS MCP server', results);\n}\n\nexport async function runMcpRemove(options: McpCommandOptions = {}): Promise<void> {\n const filter = resolveAgentFilter(options.agent);\n const clients = await detectMcpClients(filter);\n if (clients.length === 0) {\n reportNoAgents();\n return;\n }\n const results: McpClientResult[] = [];\n for (const client of clients) {\n results.push(await client.remove());\n }\n reportResults('Removed WorkOS MCP server', results);\n}\n\nexport async function runMcpStatus(): Promise<void> {\n // Status lists every known agent (not just available ones) with its\n // availability + install flags, so `createMcpClients()` — not\n // `detectMcpClients()` — is the right source here.\n const clients = createMcpClients();\n const agents = await Promise.all(\n clients.map(async (client) => {\n const available = await client.isAvailable();\n const installed = available ? await client.isInstalled() : false;\n return { agent: client.key, displayName: client.displayName, available, installed };\n }),\n );\n\n if (isJsonMode()) {\n outputJson({ data: { agents } });\n return;\n }\n\n outputTable(\n [{ header: 'Agent' }, { header: 'Available' }, { header: 'Installed' }],\n agents.map((a) => [a.displayName, a.available ? 'yes' : 'no', a.installed ? 'yes' : 'no']),\n );\n}\n"]}
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"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","sourcesContent":["import ui from '../utils/ui.js';\nimport { outputSuccess, outputJson, outputTable, exitWithError, isJsonMode } from '../utils/output.js';\nimport { ExitCode, exitWithCode } from '../utils/exit-codes.js';\nimport {\n createMcpClients,\n detectMcpClients,\n MCP_AGENT_KEYS,\n MCP_OUTCOME_LABELS,\n type McpAgentKey,\n type McpClientResult,\n} from '../lib/mcp-clients.js';\n\n/**\n * `workos mcp install | remove | status` handlers.\n *\n * Thin callers over `lib/mcp-clients.ts`: detect the clients, run the\n * operation, and format the per-agent matrix in both output modes. No prompts\n * (non-TTY-safe by construction) and no auth guard — the WorkOS MCP server is\n * secret-free, so configuring it never needs an API key.\n */\n\nexport interface McpCommandOptions {\n agent?: string[];\n}\n\n/**\n * Validate `--agent` values against known keys. Unknown values exit with a\n * structured `unknown_agent` error. Returns undefined (no filter) when none\n * were passed, so callers act on all detected agents.\n */\nfunction resolveAgentFilter(agent?: string[]): McpAgentKey[] | undefined {\n if (!agent || agent.length === 0) return undefined;\n const unknown = agent.filter((a) => !MCP_AGENT_KEYS.includes(a as McpAgentKey));\n if (unknown.length > 0) {\n exitWithError({\n code: 'unknown_agent',\n message: `Unknown agent(s): ${unknown.join(', ')}. Supported: ${MCP_AGENT_KEYS.join(', ')}.`,\n });\n }\n return agent as McpAgentKey[];\n}\n\n/** Zero detected agents: same message + exit 0 for both install and remove. */\nfunction reportNoAgents(): void {\n if (isJsonMode()) {\n outputSuccess('No supported coding agents detected', { agents: [] });\n } else {\n ui.log.info('No supported coding agents detected (looked for Claude Code, Codex, Cursor).');\n }\n}\n\n/**\n * Emit the per-agent matrix, then exit non-zero if any agent failed. The full\n * matrix is always emitted first so partial success is still fully reported.\n */\nfunction reportResults(message: string, results: McpClientResult[]): void {\n if (isJsonMode()) {\n outputSuccess(message, { agents: results });\n } else {\n for (const r of results) {\n const line = `${r.displayName}: ${MCP_OUTCOME_LABELS[r.outcome]}`;\n if (r.outcome === 'failed') {\n ui.log.error(r.error ? `${line} — ${r.error}` : line);\n } else if (r.outcome === 'installed' || r.outcome === 'removed' || r.outcome === 'already-installed') {\n ui.log.success(line);\n } else {\n ui.log.info(line);\n }\n }\n }\n\n if (results.some((r) => r.outcome === 'failed')) {\n exitWithCode(ExitCode.GENERAL_ERROR);\n }\n}\n\nexport async function runMcpInstall(options: McpCommandOptions = {}): Promise<void> {\n const filter = resolveAgentFilter(options.agent);\n const clients = await detectMcpClients(filter);\n if (clients.length === 0) {\n reportNoAgents();\n return;\n }\n const results: McpClientResult[] = [];\n for (const client of clients) {\n results.push(await client.add());\n }\n reportResults('Configured WorkOS MCP server', results);\n}\n\nexport async function runMcpRemove(options: McpCommandOptions = {}): Promise<void> {\n const filter = resolveAgentFilter(options.agent);\n const clients = await detectMcpClients(filter);\n if (clients.length === 0) {\n reportNoAgents();\n return;\n }\n const results: McpClientResult[] = [];\n for (const client of clients) {\n results.push(await client.remove());\n }\n reportResults('Removed WorkOS MCP server', results);\n}\n\nexport async function runMcpStatus(): Promise<void> {\n // Status lists every known agent (not just available ones) with its\n // availability + install flags, so `createMcpClients()` — not\n // `detectMcpClients()` — is the right source here.\n const clients = createMcpClients();\n const agents = await Promise.all(\n clients.map(async (client) => {\n const available = await client.isAvailable();\n const installed = available ? await client.isInstalled() : false;\n return { agent: client.key, displayName: client.displayName, available, installed };\n }),\n );\n\n if (isJsonMode()) {\n outputJson({ data: { agents } });\n return;\n }\n\n outputTable(\n [{ header: 'Agent' }, { header: 'Available' }, { header: 'Installed' }],\n agents.map((a) => [a.displayName, a.available ? 'yes' : 'no', a.installed ? 'yes' : 'no']),\n );\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { getWorkOSCommand } from '../utils/command-invocation.js';
1
2
  const workosOnlyMigrationsFlags = new Map([
2
3
  ['--api-key', true],
3
4
  ['--insecure-storage', false],
@@ -43,7 +44,7 @@ export async function runMigrations(args, apiKey, apiBaseUrl) {
43
44
  process.env.WORKOS_API_URL = apiBaseUrl;
44
45
  }
45
46
  const { program } = (await import('@workos/migrations/dist/cli/index.js'));
46
- program.name('workos migrations');
47
+ program.name(`${getWorkOSCommand()} migrations`);
47
48
  await program.parseAsync(args, { from: 'user' });
48
49
  }
49
50
  //# sourceMappingURL=migrations.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../src/commands/migrations.ts"],"names":[],"mappings":"AAAA,MAAM,yBAAyB,GAAG,IAAI,GAAG,CAAC;IACxC,CAAC,WAAW,EAAE,IAAI,CAAC;IACnB,CAAC,oBAAoB,EAAE,KAAK,CAAC;IAC7B,CAAC,QAAQ,EAAE,KAAK,CAAC;IACjB,CAAC,QAAQ,EAAE,IAAI,CAAC;CACjB,CAAC,CAAC;AAEH,MAAM,UAAU,4BAA4B,CAAC,OAAiB;IAC5D,IAAI,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAElD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACvB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,UAAU,GAAG,yBAAyB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEtD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,UAAU,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,CAAC,EAAE,CAAC;YAC1C,SAAS;QACX,CAAC;QAED,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YACzB,aAAa,GAAG,CAAC,CAAC;YAClB,MAAM;QACR,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,UAAU,GAAG,yBAAyB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEtD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,UAAU,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,CAAC,EAAE,CAAC;YAC1C,SAAS;QACX,CAAC;QAED,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAc,EAAE,MAAe,EAAE,UAAmB;IACtF,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,MAAM,CAAC;IACzC,CAAC;IACD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,UAAU,CAAC;IAC1C,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,MAAM,CAAC,sCAAsC,CAAC,CAKxE,CAAC;IAEF,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAClC,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AACnD,CAAC","sourcesContent":["const workosOnlyMigrationsFlags = new Map([\n ['--api-key', true],\n ['--insecure-storage', false],\n ['--json', false],\n ['--mode', true],\n]);\n\nexport function getMigrationsPassthroughArgs(rawArgs: string[]): string[] {\n let migrationsIdx = rawArgs.indexOf('migrations');\n\n for (let i = 0; i < rawArgs.length; i++) {\n const arg = rawArgs[i];\n const key = arg.split('=')[0];\n const takesValue = workosOnlyMigrationsFlags.get(key);\n\n if (takesValue !== undefined) {\n if (takesValue && !arg.includes('=')) i++;\n continue;\n }\n\n if (arg === 'migrations') {\n migrationsIdx = i;\n break;\n }\n }\n\n const after = rawArgs.slice(migrationsIdx + 1);\n const passthrough: string[] = [];\n\n for (let i = 0; i < after.length; i++) {\n const arg = after[i];\n const key = arg.split('=')[0];\n const takesValue = workosOnlyMigrationsFlags.get(key);\n\n if (takesValue !== undefined) {\n if (takesValue && !arg.includes('=')) i++;\n continue;\n }\n\n passthrough.push(arg);\n }\n\n return passthrough;\n}\n\nexport async function runMigrations(args: string[], apiKey?: string, apiBaseUrl?: string): Promise<void> {\n if (apiKey) {\n process.env.WORKOS_SECRET_KEY = apiKey;\n }\n if (apiBaseUrl) {\n process.env.WORKOS_API_URL = apiBaseUrl;\n }\n\n const { program } = (await import('@workos/migrations/dist/cli/index.js')) as {\n program: {\n name(str: string): unknown;\n parseAsync(argv: string[], options?: { from: 'user' }): Promise<unknown>;\n };\n };\n\n program.name('workos migrations');\n await program.parseAsync(args, { from: 'user' });\n}\n"]}
1
+ {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../src/commands/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE,MAAM,yBAAyB,GAAG,IAAI,GAAG,CAAC;IACxC,CAAC,WAAW,EAAE,IAAI,CAAC;IACnB,CAAC,oBAAoB,EAAE,KAAK,CAAC;IAC7B,CAAC,QAAQ,EAAE,KAAK,CAAC;IACjB,CAAC,QAAQ,EAAE,IAAI,CAAC;CACjB,CAAC,CAAC;AAEH,MAAM,UAAU,4BAA4B,CAAC,OAAiB;IAC5D,IAAI,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAElD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACvB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,UAAU,GAAG,yBAAyB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEtD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,UAAU,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,CAAC,EAAE,CAAC;YAC1C,SAAS;QACX,CAAC;QAED,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YACzB,aAAa,GAAG,CAAC,CAAC;YAClB,MAAM;QACR,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,UAAU,GAAG,yBAAyB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEtD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,UAAU,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,CAAC,EAAE,CAAC;YAC1C,SAAS;QACX,CAAC;QAED,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAc,EAAE,MAAe,EAAE,UAAmB;IACtF,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,MAAM,CAAC;IACzC,CAAC;IACD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,UAAU,CAAC;IAC1C,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,MAAM,CAAC,sCAAsC,CAAC,CAKxE,CAAC;IAEF,OAAO,CAAC,IAAI,CAAC,GAAG,gBAAgB,EAAE,aAAa,CAAC,CAAC;IACjD,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AACnD,CAAC","sourcesContent":["import { getWorkOSCommand } from '../utils/command-invocation.js';\n\nconst workosOnlyMigrationsFlags = new Map([\n ['--api-key', true],\n ['--insecure-storage', false],\n ['--json', false],\n ['--mode', true],\n]);\n\nexport function getMigrationsPassthroughArgs(rawArgs: string[]): string[] {\n let migrationsIdx = rawArgs.indexOf('migrations');\n\n for (let i = 0; i < rawArgs.length; i++) {\n const arg = rawArgs[i];\n const key = arg.split('=')[0];\n const takesValue = workosOnlyMigrationsFlags.get(key);\n\n if (takesValue !== undefined) {\n if (takesValue && !arg.includes('=')) i++;\n continue;\n }\n\n if (arg === 'migrations') {\n migrationsIdx = i;\n break;\n }\n }\n\n const after = rawArgs.slice(migrationsIdx + 1);\n const passthrough: string[] = [];\n\n for (let i = 0; i < after.length; i++) {\n const arg = after[i];\n const key = arg.split('=')[0];\n const takesValue = workosOnlyMigrationsFlags.get(key);\n\n if (takesValue !== undefined) {\n if (takesValue && !arg.includes('=')) i++;\n continue;\n }\n\n passthrough.push(arg);\n }\n\n return passthrough;\n}\n\nexport async function runMigrations(args: string[], apiKey?: string, apiBaseUrl?: string): Promise<void> {\n if (apiKey) {\n process.env.WORKOS_SECRET_KEY = apiKey;\n }\n if (apiBaseUrl) {\n process.env.WORKOS_API_URL = apiBaseUrl;\n }\n\n const { program } = (await import('@workos/migrations/dist/cli/index.js')) as {\n program: {\n name(str: string): unknown;\n parseAsync(argv: string[], options?: { from: 'user' }): Promise<unknown>;\n };\n };\n\n program.name(`${getWorkOSCommand()} migrations`);\n await program.parseAsync(args, { from: 'user' });\n}\n"]}
@@ -3,6 +3,7 @@ import chalk from 'chalk';
3
3
  import { parse as parseYaml } from 'yaml';
4
4
  import { createWorkOSClient } from '../lib/workos-client.js';
5
5
  import { outputJson, outputSuccess, isJsonMode, exitWithError } from '../utils/output.js';
6
+ import { formatWorkOSCommand } from '../utils/command-invocation.js';
6
7
  const STATE_FILE = '.workos-seed-state.json';
7
8
  function loadState() {
8
9
  if (!existsSync(STATE_FILE))
@@ -69,7 +70,7 @@ export function runSeedInit() {
69
70
  }
70
71
  else {
71
72
  console.log(chalk.green(`Created ${DEFAULT_SEED_FILE}`));
72
- console.log(chalk.dim('Edit the file, then run: workos seed --file=workos-seed.yml'));
73
+ console.log(chalk.dim(`Edit the file, then run: ${formatWorkOSCommand('seed --file=workos-seed.yml')}`));
73
74
  }
74
75
  }
75
76
  export async function runSeed(options, apiKey, baseUrl) {
@@ -84,13 +85,13 @@ export async function runSeed(options, apiKey, baseUrl) {
84
85
  if (!options.file) {
85
86
  return exitWithError({
86
87
  code: 'missing_args',
87
- message: 'Provide a seed file: workos seed --file=workos-seed.yml\nRun workos seed --init to create an example seed file.',
88
+ message: `Provide a seed file: ${formatWorkOSCommand('seed --file=workos-seed.yml')}\nRun ${formatWorkOSCommand('seed --init')} to create an example seed file.`,
88
89
  });
89
90
  }
90
91
  if (!existsSync(options.file)) {
91
92
  return exitWithError({
92
93
  code: 'file_not_found',
93
- message: `Seed file not found: ${options.file}. Create workos-seed.yml or run \`workos seed\` without --file for interactive mode.`,
94
+ message: `Seed file not found: ${options.file}. Create workos-seed.yml or run \`${formatWorkOSCommand('seed')}\` without --file for interactive mode.`,
94
95
  });
95
96
  }
96
97
  const raw = readFileSync(options.file, 'utf-8');
@@ -211,7 +212,7 @@ export async function runSeed(options, apiKey, baseUrl) {
211
212
  saveState(state);
212
213
  exitWithError({
213
214
  code: 'seed_failed',
214
- message: `Seed failed: ${error instanceof Error ? error.message : 'Unknown error'}. Partial state saved to ${STATE_FILE}. Run \`workos seed --clean\` to tear down.`,
215
+ message: `Seed failed: ${error instanceof Error ? error.message : 'Unknown error'}. Partial state saved to ${STATE_FILE}. Run \`${formatWorkOSCommand('seed --clean')}\` to tear down.`,
215
216
  details: state,
216
217
  });
217
218
  }