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 +1 @@
1
- {"version":3,"file":"config-store.js","sourceRoot":"","sources":["../../src/lib/config-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * CLI config storage abstraction with keyring support and file fallback.\n *\n * Stores environment configurations (names, API keys, endpoints) separately\n * from OAuth credentials. Uses a second keyring entry under the same service.\n *\n * Storage priority:\n * 1. If insecure storage forced: use file only\n * 2. Try keyring, fall back to file with warning if unavailable\n */\n\nimport { Entry } from '@napi-rs/keyring';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { logWarn } from '../utils/debug.js';\nimport { observeHostFailure } from './host-probe.js';\n\ninterface BaseEnvironmentConfig {\n name: string;\n apiKey: string;\n endpoint?: string;\n}\n\nexport interface ClaimedEnvironmentConfig extends BaseEnvironmentConfig {\n type: 'production' | 'sandbox';\n clientId?: string;\n}\n\nexport interface UnclaimedEnvironmentConfig extends BaseEnvironmentConfig {\n type: 'unclaimed';\n clientId: string;\n claimToken: string;\n}\n\nexport type EnvironmentConfig = ClaimedEnvironmentConfig | UnclaimedEnvironmentConfig;\n\n/**\n * Type guard — narrows to UnclaimedEnvironmentConfig with required clientId and claimToken.\n */\nexport function isUnclaimedEnvironment(env: EnvironmentConfig): env is UnclaimedEnvironmentConfig {\n return env.type === 'unclaimed';\n}\n\nexport interface CliConfig {\n activeEnvironment?: string;\n environments: Record<string, EnvironmentConfig>;\n}\n\nconst SERVICE_NAME = 'workos-cli';\nconst ACCOUNT_NAME = 'config';\n\nlet fallbackWarningShown = false;\nlet forceInsecureStorage = false;\nlet migrationAttempted = false;\n\nexport function setInsecureConfigStorage(value: boolean): void {\n forceInsecureStorage = value;\n migrationAttempted = false;\n}\n\nfunction getConfigDir(): string {\n return path.join(os.homedir(), '.workos');\n}\n\nfunction getConfigFilePath(): string {\n return path.join(getConfigDir(), 'config.json');\n}\n\nfunction fileExists(): boolean {\n return fs.existsSync(getConfigFilePath());\n}\n\nfunction readFromFile(): CliConfig | null {\n if (!fileExists()) return null;\n const filePath = getConfigFilePath();\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n return JSON.parse(content);\n } catch (error) {\n observeHostFailure('home-fs', error, {\n operation: 'read',\n target: filePath,\n label: 'config fallback file',\n });\n logWarn('Failed to read config file:', error);\n return null;\n }\n}\n\nfunction writeToFile(config: CliConfig): void {\n const dir = getConfigDir();\n const filePath = getConfigFilePath();\n try {\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n fs.writeFileSync(filePath, JSON.stringify(config, null, 2), {\n mode: 0o600,\n });\n } catch (error) {\n observeHostFailure('home-fs', error, {\n operation: 'write',\n target: filePath,\n label: 'config fallback file',\n });\n throw error;\n }\n}\n\nfunction deleteFile(): void {\n const filePath = getConfigFilePath();\n if (fileExists()) {\n try {\n fs.unlinkSync(filePath);\n } catch (error) {\n observeHostFailure('home-fs', error, {\n operation: 'delete',\n target: filePath,\n label: 'config fallback file',\n });\n throw error;\n }\n }\n}\n\nfunction getKeyringEntry(): Entry {\n return new Entry(SERVICE_NAME, ACCOUNT_NAME);\n}\n\nfunction readFromKeyring(): CliConfig | null {\n try {\n const entry = getKeyringEntry();\n const data = entry.getPassword();\n if (!data) return null;\n return JSON.parse(data);\n } catch (error) {\n logWarn('Failed to read config from keyring:', error);\n observeHostFailure('keychain', error, {\n operation: 'read',\n target: `${SERVICE_NAME}/${ACCOUNT_NAME}`,\n label: 'config keychain entry',\n });\n return null;\n }\n}\n\nfunction writeToKeyring(config: CliConfig): boolean {\n try {\n const entry = getKeyringEntry();\n entry.setPassword(JSON.stringify(config));\n return true;\n } catch (error) {\n logWarn('Failed to write config to keyring:', error);\n observeHostFailure('keychain', error, {\n operation: 'write',\n target: `${SERVICE_NAME}/${ACCOUNT_NAME}`,\n label: 'config keychain entry',\n });\n return false;\n }\n}\n\nfunction deleteFromKeyring(): void {\n try {\n const entry = getKeyringEntry();\n entry.deletePassword();\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n if (!msg.includes('not found') && !msg.includes('No such')) {\n logWarn('Failed to delete config from keyring:', error);\n observeHostFailure('keychain', error, {\n operation: 'delete',\n target: `${SERVICE_NAME}/${ACCOUNT_NAME}`,\n label: 'config keychain entry',\n });\n }\n }\n}\n\nfunction showFallbackWarning(): void {\n if (fallbackWarningShown || forceInsecureStorage) return;\n fallbackWarningShown = true;\n logWarn(\n 'Unable to store config in system keyring. Using file storage.',\n 'Config saved to ~/.workos/config.json',\n 'Use --insecure-storage to suppress this warning.',\n );\n}\n\nexport function getConfig(): CliConfig | null {\n if (forceInsecureStorage) return readFromFile();\n\n const keyringConfig = readFromKeyring();\n if (keyringConfig) return keyringConfig;\n\n const fileConfig = readFromFile();\n if (fileConfig) {\n if (!migrationAttempted) {\n migrationAttempted = true;\n writeToKeyring(fileConfig);\n }\n return fileConfig;\n }\n\n return null;\n}\n\nexport function saveConfig(config: CliConfig): void {\n if (forceInsecureStorage) return writeToFile(config);\n\n if (!writeToKeyring(config)) {\n showFallbackWarning();\n writeToFile(config);\n return;\n }\n\n // Verify the keyring write is readable (guards against silent keyring failures\n // where setPassword succeeds but getPassword returns null in the same process)\n if (!readFromKeyring()) {\n logWarn('Keyring write succeeded but read-back failed — falling back to file');\n writeToFile(config);\n }\n}\n\nexport function clearConfig(): void {\n deleteFromKeyring();\n deleteFile();\n migrationAttempted = false;\n}\n\nexport function getActiveEnvironment(): EnvironmentConfig | null {\n const config = getConfig();\n if (!config?.activeEnvironment) return null;\n return config.environments[config.activeEnvironment] ?? null;\n}\n\nexport function getConfigPath(): string {\n return getConfigFilePath();\n}\n\n/**\n * Diagnostic info about config storage state — for debugging config persistence failures.\n */\nexport function diagnoseConfig(): string[] {\n const lines: string[] = [];\n const filePath = getConfigFilePath();\n const filePresent = fileExists();\n\n lines.push(`file: ${filePath} (exists=${filePresent})`);\n\n if (filePresent) {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const parsed = JSON.parse(content) as Partial<CliConfig>;\n const envCount = parsed.environments ? Object.keys(parsed.environments).length : 0;\n lines.push(`file config: active=${parsed.activeEnvironment ?? 'none'}, environments=${envCount}`);\n } catch (e) {\n lines.push(`file config: parse error — ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n\n try {\n const entry = getKeyringEntry();\n const data = entry.getPassword();\n if (data) {\n const parsed = JSON.parse(data) as Partial<CliConfig>;\n const envCount = parsed.environments ? Object.keys(parsed.environments).length : 0;\n lines.push(`keyring: found, active=${parsed.activeEnvironment ?? 'none'}, environments=${envCount}`);\n } else {\n lines.push('keyring: empty (getPassword returned null)');\n }\n } catch (e) {\n lines.push(`keyring: error — ${e instanceof Error ? e.message : String(e)}`);\n }\n\n lines.push(`insecureStorage=${forceInsecureStorage}`);\n return lines;\n}\n\n/**\n * Mark the active unclaimed environment as claimed.\n * Updates type to 'sandbox', removes the claim token, and renames\n * the environment key from 'unclaimed' to 'sandbox'.\n */\nexport function markEnvironmentClaimed(): void {\n const config = getConfig();\n if (!config?.activeEnvironment) return;\n const oldKey = config.activeEnvironment;\n const env = config.environments[oldKey];\n if (env && env.type === 'unclaimed') {\n // Pick a key that won't overwrite an existing environment\n let newKey = 'sandbox';\n if (oldKey !== newKey && config.environments[newKey]) {\n newKey = oldKey; // keep existing key if 'sandbox' is already taken\n }\n\n const claimed: ClaimedEnvironmentConfig = {\n name: newKey,\n type: 'sandbox',\n apiKey: env.apiKey,\n clientId: env.clientId,\n ...(env.endpoint && { endpoint: env.endpoint }),\n };\n\n if (oldKey !== newKey) {\n delete config.environments[oldKey];\n }\n config.environments[newKey] = claimed;\n config.activeEnvironment = newKey;\n\n saveConfig(config);\n }\n}\n"]}
1
+ {"version":3,"file":"config-store.js","sourceRoot":"","sources":["../../src/lib/config-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * CLI config storage abstraction with keyring support and file fallback.\n *\n * Stores environment configurations (names, API keys, endpoints) separately\n * from OAuth credentials. Uses a second keyring entry under the same service.\n *\n * Storage priority:\n * 1. If insecure storage forced: use file only\n * 2. Try keyring, fall back to file with warning if unavailable\n */\n\nimport { Entry } from '@napi-rs/keyring';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { logWarn } from '../utils/debug.js';\nimport { observeHostFailure } from './host-probe.js';\n\ninterface BaseEnvironmentConfig {\n name: string;\n apiKey: string;\n endpoint?: string;\n /** Email of the account that owns this environment. Stamped when `auth login` provisions Staging for a known account; undefined for unclaimed/manually-added envs. */\n ownerEmail?: string;\n /** User ID of the account that owns this environment. Stamped alongside ownerEmail. */\n ownerUserId?: string;\n}\n\nexport interface ClaimedEnvironmentConfig extends BaseEnvironmentConfig {\n type: 'production' | 'sandbox';\n clientId?: string;\n}\n\nexport interface UnclaimedEnvironmentConfig extends BaseEnvironmentConfig {\n type: 'unclaimed';\n clientId: string;\n claimToken: string;\n}\n\nexport type EnvironmentConfig = ClaimedEnvironmentConfig | UnclaimedEnvironmentConfig;\n\n/**\n * Type guard — narrows to UnclaimedEnvironmentConfig with required clientId and claimToken.\n */\nexport function isUnclaimedEnvironment(env: EnvironmentConfig): env is UnclaimedEnvironmentConfig {\n return env.type === 'unclaimed';\n}\n\nexport interface CliConfig {\n activeEnvironment?: string;\n environments: Record<string, EnvironmentConfig>;\n}\n\nconst SERVICE_NAME = 'workos-cli';\nconst ACCOUNT_NAME = 'config';\n\nlet fallbackWarningShown = false;\nlet forceInsecureStorage = false;\nlet migrationAttempted = false;\n\nexport function setInsecureConfigStorage(value: boolean): void {\n forceInsecureStorage = value;\n migrationAttempted = false;\n}\n\nfunction getConfigDir(): string {\n return path.join(os.homedir(), '.workos');\n}\n\nfunction getConfigFilePath(): string {\n return path.join(getConfigDir(), 'config.json');\n}\n\nfunction fileExists(): boolean {\n return fs.existsSync(getConfigFilePath());\n}\n\nfunction readFromFile(): CliConfig | null {\n if (!fileExists()) return null;\n const filePath = getConfigFilePath();\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n return JSON.parse(content);\n } catch (error) {\n observeHostFailure('home-fs', error, {\n operation: 'read',\n target: filePath,\n label: 'config fallback file',\n });\n logWarn('Failed to read config file:', error);\n return null;\n }\n}\n\nfunction writeToFile(config: CliConfig): void {\n const dir = getConfigDir();\n const filePath = getConfigFilePath();\n try {\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n fs.writeFileSync(filePath, JSON.stringify(config, null, 2), {\n mode: 0o600,\n });\n } catch (error) {\n observeHostFailure('home-fs', error, {\n operation: 'write',\n target: filePath,\n label: 'config fallback file',\n });\n throw error;\n }\n}\n\nfunction deleteFile(): void {\n const filePath = getConfigFilePath();\n if (fileExists()) {\n try {\n fs.unlinkSync(filePath);\n } catch (error) {\n observeHostFailure('home-fs', error, {\n operation: 'delete',\n target: filePath,\n label: 'config fallback file',\n });\n throw error;\n }\n }\n}\n\nfunction getKeyringEntry(): Entry {\n return new Entry(SERVICE_NAME, ACCOUNT_NAME);\n}\n\nfunction readFromKeyring(): CliConfig | null {\n try {\n const entry = getKeyringEntry();\n const data = entry.getPassword();\n if (!data) return null;\n return JSON.parse(data);\n } catch (error) {\n logWarn('Failed to read config from keyring:', error);\n observeHostFailure('keychain', error, {\n operation: 'read',\n target: `${SERVICE_NAME}/${ACCOUNT_NAME}`,\n label: 'config keychain entry',\n });\n return null;\n }\n}\n\nfunction writeToKeyring(config: CliConfig): boolean {\n try {\n const entry = getKeyringEntry();\n entry.setPassword(JSON.stringify(config));\n return true;\n } catch (error) {\n logWarn('Failed to write config to keyring:', error);\n observeHostFailure('keychain', error, {\n operation: 'write',\n target: `${SERVICE_NAME}/${ACCOUNT_NAME}`,\n label: 'config keychain entry',\n });\n return false;\n }\n}\n\nfunction deleteFromKeyring(): void {\n try {\n const entry = getKeyringEntry();\n entry.deletePassword();\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n if (!msg.includes('not found') && !msg.includes('No such')) {\n logWarn('Failed to delete config from keyring:', error);\n observeHostFailure('keychain', error, {\n operation: 'delete',\n target: `${SERVICE_NAME}/${ACCOUNT_NAME}`,\n label: 'config keychain entry',\n });\n }\n }\n}\n\nfunction showFallbackWarning(): void {\n if (fallbackWarningShown || forceInsecureStorage) return;\n fallbackWarningShown = true;\n logWarn(\n 'Unable to store config in system keyring. Using file storage.',\n 'Config saved to ~/.workos/config.json',\n 'Use --insecure-storage to suppress this warning.',\n );\n}\n\nexport function getConfig(): CliConfig | null {\n if (forceInsecureStorage) return readFromFile();\n\n const keyringConfig = readFromKeyring();\n if (keyringConfig) return keyringConfig;\n\n const fileConfig = readFromFile();\n if (fileConfig) {\n if (!migrationAttempted) {\n migrationAttempted = true;\n writeToKeyring(fileConfig);\n }\n return fileConfig;\n }\n\n return null;\n}\n\nexport function saveConfig(config: CliConfig): void {\n if (forceInsecureStorage) return writeToFile(config);\n\n if (!writeToKeyring(config)) {\n showFallbackWarning();\n writeToFile(config);\n return;\n }\n\n // Verify the keyring write is readable (guards against silent keyring failures\n // where setPassword succeeds but getPassword returns null in the same process)\n if (!readFromKeyring()) {\n logWarn('Keyring write succeeded but read-back failed — falling back to file');\n writeToFile(config);\n }\n}\n\nexport function clearConfig(): void {\n deleteFromKeyring();\n deleteFile();\n migrationAttempted = false;\n}\n\nexport function getActiveEnvironment(): EnvironmentConfig | null {\n const config = getConfig();\n if (!config?.activeEnvironment) return null;\n return config.environments[config.activeEnvironment] ?? null;\n}\n\n/**\n * Set the active environment by name.\n *\n * No-op when there is no config or the named environment does not exist —\n * callers should not be able to point `activeEnvironment` at a missing key.\n */\nexport function setActiveEnvironment(name: string): void {\n const config = getConfig();\n if (!config || !config.environments[name]) return;\n config.activeEnvironment = name;\n saveConfig(config);\n}\n\n/** Pick a non-colliding environments key: `base`, else `base-2`, `base-3`, … */\nexport function freshEnvKey(config: CliConfig, base: string): string {\n if (!config.environments[base]) return base;\n let i = 2;\n while (config.environments[`${base}-${i}`]) i++;\n return `${base}-${i}`;\n}\n\nexport function getConfigPath(): string {\n return getConfigFilePath();\n}\n\n/**\n * Diagnostic info about config storage state — for debugging config persistence failures.\n */\nexport function diagnoseConfig(): string[] {\n const lines: string[] = [];\n const filePath = getConfigFilePath();\n const filePresent = fileExists();\n\n lines.push(`file: ${filePath} (exists=${filePresent})`);\n\n if (filePresent) {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const parsed = JSON.parse(content) as Partial<CliConfig>;\n const envCount = parsed.environments ? Object.keys(parsed.environments).length : 0;\n lines.push(`file config: active=${parsed.activeEnvironment ?? 'none'}, environments=${envCount}`);\n } catch (e) {\n lines.push(`file config: parse error — ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n\n try {\n const entry = getKeyringEntry();\n const data = entry.getPassword();\n if (data) {\n const parsed = JSON.parse(data) as Partial<CliConfig>;\n const envCount = parsed.environments ? Object.keys(parsed.environments).length : 0;\n lines.push(`keyring: found, active=${parsed.activeEnvironment ?? 'none'}, environments=${envCount}`);\n } else {\n lines.push('keyring: empty (getPassword returned null)');\n }\n } catch (e) {\n lines.push(`keyring: error — ${e instanceof Error ? e.message : String(e)}`);\n }\n\n lines.push(`insecureStorage=${forceInsecureStorage}`);\n return lines;\n}\n\n/**\n * Mark the active unclaimed environment as claimed.\n * Updates type to 'sandbox', removes the claim token, and renames\n * the environment key from 'unclaimed' to 'sandbox'.\n */\nexport function markEnvironmentClaimed(): void {\n const config = getConfig();\n if (!config?.activeEnvironment) return;\n const oldKey = config.activeEnvironment;\n const env = config.environments[oldKey];\n if (env && env.type === 'unclaimed') {\n // Pick a key that won't overwrite an existing environment\n let newKey = 'sandbox';\n if (oldKey !== newKey && config.environments[newKey]) {\n newKey = oldKey; // keep existing key if 'sandbox' is already taken\n }\n\n const claimed: ClaimedEnvironmentConfig = {\n name: newKey,\n type: 'sandbox',\n apiKey: env.apiKey,\n clientId: env.clientId,\n ...(env.endpoint && { endpoint: env.endpoint }),\n ...(env.ownerEmail && { ownerEmail: env.ownerEmail }),\n ...(env.ownerUserId && { ownerUserId: env.ownerUserId }),\n };\n\n if (oldKey !== newKey) {\n delete config.environments[oldKey];\n }\n config.environments[newKey] = claimed;\n config.activeEnvironment = newKey;\n\n saveConfig(config);\n }\n}\n"]}
@@ -25,7 +25,7 @@ export type IntegrationConfig = {
25
25
  };
26
26
  /**
27
27
  * Legacy detection configs for existing JS integrations.
28
- * Used by clack-utils.ts for abort/cancel messages.
28
+ * Used by ui-utils.ts for abort/cancel messages.
29
29
  * New integrations do NOT need to be added here.
30
30
  */
31
31
  export declare const INTEGRATION_CONFIG: Record<string, {
@@ -9,7 +9,7 @@
9
9
  */
10
10
  /**
11
11
  * Legacy detection configs for existing JS integrations.
12
- * Used by clack-utils.ts for abort/cancel messages.
12
+ * Used by ui-utils.ts for abort/cancel messages.
13
13
  * New integrations do NOT need to be added here.
14
14
  */
15
15
  export const INTEGRATION_CONFIG = {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoBH;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAsD;IACnF,MAAM,EAAE;QACN,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,wDAAwD;KAClE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,uDAAuD;KACjE;IACD,gBAAgB,EAAE;QAChB,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,gEAAgE;KAC1E;IACD,cAAc,EAAE;QACd,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,8DAA8D;KACxE;IACD,YAAY,EAAE;QACZ,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,4DAA4D;KACtE;CACF,CAAC","sourcesContent":["/**\n * Integration detection configuration.\n *\n * This module previously held hardcoded INTEGRATION_CONFIG and INTEGRATION_ORDER.\n * These are now provided by the auto-discovery registry (src/lib/registry.ts).\n *\n * This file is kept for backwards compatibility — functions that previously\n * used INTEGRATION_CONFIG now delegate to the registry.\n */\n\nimport type { InstallerOptions } from '../utils/types.js';\n\n/**\n * @deprecated Use registry.detectionOrder() + config.detection.detect() instead.\n * This type is kept for any code that still references it.\n */\nexport type IntegrationConfig = {\n name: string;\n filterPatterns: string[];\n ignorePatterns: string[];\n detect: (options: Pick<InstallerOptions, 'installDir'>) => Promise<boolean>;\n generateFilesRules: string;\n filterFilesRules: string;\n docsUrl: string;\n nextSteps: string;\n defaultChanges: string;\n};\n\n/**\n * Legacy detection configs for existing JS integrations.\n * Used by clack-utils.ts for abort/cancel messages.\n * New integrations do NOT need to be added here.\n */\nexport const INTEGRATION_CONFIG: Record<string, { docsUrl: string; name: string }> = {\n nextjs: {\n name: 'Next.js',\n docsUrl: 'https://workos.com/docs/user-management/authkit/nextjs',\n },\n react: {\n name: 'React (SPA)',\n docsUrl: 'https://workos.com/docs/user-management/authkit/react',\n },\n 'tanstack-start': {\n name: 'TanStack Start',\n docsUrl: 'https://workos.com/docs/user-management/authkit/tanstack-start',\n },\n 'react-router': {\n name: 'React Router',\n docsUrl: 'https://workos.com/docs/user-management/authkit/react-router',\n },\n 'vanilla-js': {\n name: 'Vanilla JavaScript',\n docsUrl: 'https://workos.com/docs/user-management/authkit/javascript',\n },\n};\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoBH;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAsD;IACnF,MAAM,EAAE;QACN,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,wDAAwD;KAClE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,uDAAuD;KACjE;IACD,gBAAgB,EAAE;QAChB,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,gEAAgE;KAC1E;IACD,cAAc,EAAE;QACd,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,8DAA8D;KACxE;IACD,YAAY,EAAE;QACZ,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,4DAA4D;KACtE;CACF,CAAC","sourcesContent":["/**\n * Integration detection configuration.\n *\n * This module previously held hardcoded INTEGRATION_CONFIG and INTEGRATION_ORDER.\n * These are now provided by the auto-discovery registry (src/lib/registry.ts).\n *\n * This file is kept for backwards compatibility — functions that previously\n * used INTEGRATION_CONFIG now delegate to the registry.\n */\n\nimport type { InstallerOptions } from '../utils/types.js';\n\n/**\n * @deprecated Use registry.detectionOrder() + config.detection.detect() instead.\n * This type is kept for any code that still references it.\n */\nexport type IntegrationConfig = {\n name: string;\n filterPatterns: string[];\n ignorePatterns: string[];\n detect: (options: Pick<InstallerOptions, 'installDir'>) => Promise<boolean>;\n generateFilesRules: string;\n filterFilesRules: string;\n docsUrl: string;\n nextSteps: string;\n defaultChanges: string;\n};\n\n/**\n * Legacy detection configs for existing JS integrations.\n * Used by ui-utils.ts for abort/cancel messages.\n * New integrations do NOT need to be added here.\n */\nexport const INTEGRATION_CONFIG: Record<string, { docsUrl: string; name: string }> = {\n nextjs: {\n name: 'Next.js',\n docsUrl: 'https://workos.com/docs/user-management/authkit/nextjs',\n },\n react: {\n name: 'React (SPA)',\n docsUrl: 'https://workos.com/docs/user-management/authkit/react',\n },\n 'tanstack-start': {\n name: 'TanStack Start',\n docsUrl: 'https://workos.com/docs/user-management/authkit/tanstack-start',\n },\n 'react-router': {\n name: 'React Router',\n docsUrl: 'https://workos.com/docs/user-management/authkit/react-router',\n },\n 'vanilla-js': {\n name: 'Vanilla JavaScript',\n docsUrl: 'https://workos.com/docs/user-management/authkit/javascript',\n },\n};\n"]}
@@ -36,6 +36,14 @@ export declare const OAUTH_PORT: number;
36
36
  */
37
37
  export declare const MCP_SERVER_NAME = "workos";
38
38
  export declare const MCP_SERVER_URL = "https://mcp.workos.com/mcp";
39
+ /**
40
+ * Shared description for the `migrations` command, referenced by both the yargs
41
+ * registration (`bin.ts`) and the JSON help registry (`help-json.ts`) so the two
42
+ * surfaces cannot drift. Advertises the generic-CSV path (e.g. Supabase) without
43
+ * implying a dedicated exporter exists for it. Hand-maintained — not derived from
44
+ * `@workos/migrations`.
45
+ */
46
+ export declare const MIGRATIONS_DESCRIPTION = "Migrate users to WorkOS from Auth0, Cognito, Clerk, Firebase, or any provider via CSV (e.g. Supabase)";
39
47
  /**
40
48
  * Common glob patterns to ignore when searching for files.
41
49
  * Used by multiple integrations.
@@ -28,6 +28,14 @@ export const OAUTH_PORT = settings.legacy.oauthPort;
28
28
  */
29
29
  export const MCP_SERVER_NAME = 'workos';
30
30
  export const MCP_SERVER_URL = 'https://mcp.workos.com/mcp';
31
+ /**
32
+ * Shared description for the `migrations` command, referenced by both the yargs
33
+ * registration (`bin.ts`) and the JSON help registry (`help-json.ts`) so the two
34
+ * surfaces cannot drift. Advertises the generic-CSV path (e.g. Supabase) without
35
+ * implying a dedicated exporter exists for it. Hand-maintained — not derived from
36
+ * `@workos/migrations`.
37
+ */
38
+ export const MIGRATIONS_DESCRIPTION = 'Migrate users to WorkOS from Auth0, Cognito, Clerk, Firebase, or any provider via CSV (e.g. Supabase)';
31
39
  /**
32
40
  * Common glob patterns to ignore when searching for files.
33
41
  * Used by multiple integrations.
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAS1C;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;IACd,aAAa,EAAE,gBAAgB;IAC/B,WAAW,EAAE,cAAc;IAC3B,SAAS,EAAE,YAAY;CACf,CAAC;AAOX,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;AAEnF,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;AAE7B,MAAM,CAAC,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC;AAChD,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC;AACpE,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC;AACxE,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC;AAC3D,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC;AAC5D,MAAM,CAAC,MAAM,gCAAgC,GAAG,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC;AAC7E,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAG,4BAA4B,CAAC;AAE3D;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAa;IACvC,oBAAoB;IACpB,YAAY;IACZ,aAAa;IACb,cAAc;IACd,aAAa;CACd,CAAC","sourcesContent":["import { getConfig } from './settings.js';\n\n/**\n * Integration identifier type.\n * No longer an enum — each integration self-registers via the auto-discovery registry.\n * The string value matches the integration directory name (e.g., 'nextjs', 'react-router').\n */\nexport type Integration = string;\n\n/**\n * Well-known integration names for backwards compatibility.\n * New integrations do NOT need to be added here — they're auto-discovered.\n */\nexport const KNOWN_INTEGRATIONS = {\n nextjs: 'nextjs',\n react: 'react',\n tanstackStart: 'tanstack-start',\n reactRouter: 'react-router',\n vanillaJs: 'vanilla-js',\n} as const;\n\nexport interface Args {\n debug: boolean;\n integration: Integration;\n}\n\nexport const IS_DEV = ['test', 'development'].includes(process.env.NODE_ENV ?? '');\n\nconst settings = getConfig();\n\nexport const DEBUG = settings.logging.debugMode;\nexport const WORKOS_DOCS_URL = settings.documentation.workosDocsUrl;\nexport const WORKOS_DASHBOARD_URL = settings.documentation.dashboardUrl;\nexport const ISSUES_URL = settings.documentation.issuesUrl;\nexport const ANALYTICS_ENABLED = settings.telemetry.enabled;\nexport const INSTALLER_INTERACTION_EVENT_NAME = settings.telemetry.eventName;\nexport const OAUTH_PORT = settings.legacy.oauthPort;\n\n/**\n * WorkOS MCP server identity, shared by the `mcp` command group and the\n * per-client writers in `lib/mcp-clients.ts`.\n *\n * The server is secret-free: HTTP transport with OAuth handled by each client\n * on first connect, so configuring it never requires CLI auth.\n */\nexport const MCP_SERVER_NAME = 'workos';\nexport const MCP_SERVER_URL = 'https://mcp.workos.com/mcp';\n\n/**\n * Common glob patterns to ignore when searching for files.\n * Used by multiple integrations.\n */\nexport const IGNORE_PATTERNS: string[] = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/public/**',\n '**/.next/**',\n];\n"]}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAS1C;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;IACd,aAAa,EAAE,gBAAgB;IAC/B,WAAW,EAAE,cAAc;IAC3B,SAAS,EAAE,YAAY;CACf,CAAC;AAOX,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;AAEnF,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;AAE7B,MAAM,CAAC,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC;AAChD,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC;AACpE,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC;AACxE,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC;AAC3D,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC;AAC5D,MAAM,CAAC,MAAM,gCAAgC,GAAG,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC;AAC7E,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAG,4BAA4B,CAAC;AAE3D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GACjC,uGAAuG,CAAC;AAE1G;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAa;IACvC,oBAAoB;IACpB,YAAY;IACZ,aAAa;IACb,cAAc;IACd,aAAa;CACd,CAAC","sourcesContent":["import { getConfig } from './settings.js';\n\n/**\n * Integration identifier type.\n * No longer an enum — each integration self-registers via the auto-discovery registry.\n * The string value matches the integration directory name (e.g., 'nextjs', 'react-router').\n */\nexport type Integration = string;\n\n/**\n * Well-known integration names for backwards compatibility.\n * New integrations do NOT need to be added here — they're auto-discovered.\n */\nexport const KNOWN_INTEGRATIONS = {\n nextjs: 'nextjs',\n react: 'react',\n tanstackStart: 'tanstack-start',\n reactRouter: 'react-router',\n vanillaJs: 'vanilla-js',\n} as const;\n\nexport interface Args {\n debug: boolean;\n integration: Integration;\n}\n\nexport const IS_DEV = ['test', 'development'].includes(process.env.NODE_ENV ?? '');\n\nconst settings = getConfig();\n\nexport const DEBUG = settings.logging.debugMode;\nexport const WORKOS_DOCS_URL = settings.documentation.workosDocsUrl;\nexport const WORKOS_DASHBOARD_URL = settings.documentation.dashboardUrl;\nexport const ISSUES_URL = settings.documentation.issuesUrl;\nexport const ANALYTICS_ENABLED = settings.telemetry.enabled;\nexport const INSTALLER_INTERACTION_EVENT_NAME = settings.telemetry.eventName;\nexport const OAUTH_PORT = settings.legacy.oauthPort;\n\n/**\n * WorkOS MCP server identity, shared by the `mcp` command group and the\n * per-client writers in `lib/mcp-clients.ts`.\n *\n * The server is secret-free: HTTP transport with OAuth handled by each client\n * on first connect, so configuring it never requires CLI auth.\n */\nexport const MCP_SERVER_NAME = 'workos';\nexport const MCP_SERVER_URL = 'https://mcp.workos.com/mcp';\n\n/**\n * Shared description for the `migrations` command, referenced by both the yargs\n * registration (`bin.ts`) and the JSON help registry (`help-json.ts`) so the two\n * surfaces cannot drift. Advertises the generic-CSV path (e.g. Supabase) without\n * implying a dedicated exporter exists for it. Hand-maintained — not derived from\n * `@workos/migrations`.\n */\nexport const MIGRATIONS_DESCRIPTION =\n 'Migrate users to WorkOS from Auth0, Cognito, Clerk, Firebase, or any provider via CSV (e.g. Supabase)';\n\n/**\n * Common glob patterns to ignore when searching for files.\n * Used by multiple integrations.\n */\nexport const IGNORE_PATTERNS: string[] = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/public/**',\n '**/.next/**',\n];\n"]}
@@ -1,4 +1,30 @@
1
1
  import { EventEmitter } from 'events';
2
+ /**
3
+ * Structured data describing a successful installation, used to render the
4
+ * completion summary and enrich the headless `complete` NDJSON event.
5
+ *
6
+ * Defined here (not in installer-core.types.ts) to avoid an import cycle:
7
+ * installer-core.types.ts already imports from this module, so this module
8
+ * must not import back.
9
+ */
10
+ export interface CompletionData {
11
+ /** Integration identifier (e.g. 'nextjs') */
12
+ integration: string;
13
+ /** Lockfile-aware dev command, e.g. "pnpm run dev" */
14
+ devCommand: string;
15
+ /** App URL with the detected port, e.g. "http://localhost:3000" */
16
+ url: string;
17
+ /** Changed files (git-relative), full list — display cap lives in the renderer */
18
+ files: string[];
19
+ /** Composed concrete + framework next-step lines */
20
+ nextSteps: string[];
21
+ /** Per-framework docs URL */
22
+ docsUrl: string;
23
+ /** WorkOS dashboard URL */
24
+ dashboardUrl: string;
25
+ /** Optional per-framework "add a sign-in link" snippet */
26
+ signInSnippet?: string;
27
+ }
2
28
  export interface InstallerEvents {
3
29
  status: {
4
30
  message: string;
@@ -45,6 +71,7 @@ export interface InstallerEvents {
45
71
  complete: {
46
72
  success: boolean;
47
73
  summary?: string;
74
+ completion?: CompletionData;
48
75
  };
49
76
  error: {
50
77
  message: string;
@@ -103,7 +130,9 @@ export interface InstallerEvents {
103
130
  message: string;
104
131
  };
105
132
  'staging:fetching': Record<string, never>;
106
- 'staging:success': Record<string, never>;
133
+ 'staging:success': {
134
+ source?: 'device' | 'stored';
135
+ };
107
136
  'staging:error': {
108
137
  message: string;
109
138
  statusCode?: number;
@@ -126,6 +155,10 @@ export interface InstallerEvents {
126
155
  attempt: number;
127
156
  maxRetries: number;
128
157
  };
158
+ 'agent:tool': {
159
+ kind: 'command';
160
+ detail: string;
161
+ };
129
162
  'validation:retry:start': {
130
163
  attempt: number;
131
164
  };
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/lib/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAoGtC,MAAM,OAAO,qBAAsB,SAAQ,YAAY;IACrD,IAAI,CAA+B,KAAQ,EAAE,OAA2B;QACtE,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,EAAE,CAA+B,KAAQ,EAAE,QAA+C;QACxF,OAAO,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,GAAG,CAA+B,KAAQ,EAAE,QAA+C;QACzF,OAAO,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,CAA+B,KAAQ,EAAE,QAA+C;QAC1F,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC;CACF;AAED,MAAM,UAAU,2BAA2B;IACzC,OAAO,IAAI,qBAAqB,EAAE,CAAC;AACrC,CAAC","sourcesContent":["import { EventEmitter } from 'events';\n\nexport interface InstallerEvents {\n status: { message: string };\n output: { text: string; isError?: boolean };\n 'file:write': { path: string; content: string };\n 'file:edit': { path: string; oldContent: string; newContent: string };\n 'prompt:request': { id: string; message: string; options?: string[] };\n 'prompt:response': { id: string; value: string };\n 'confirm:request': { id: string; message: string; warning?: string; files?: string[] };\n 'confirm:response': { id: string; confirmed: boolean };\n 'credentials:request': { requiresApiKey: boolean };\n 'credentials:response': { apiKey: string; clientId: string };\n complete: { success: boolean; summary?: string };\n error: { message: string; stack?: string };\n\n 'state:enter': { state: string };\n 'state:exit': { state: string };\n 'auth:checking': Record<string, never>;\n 'auth:required': Record<string, never>;\n 'auth:success': Record<string, never>;\n 'auth:failure': { message: string };\n 'detection:start': Record<string, never>;\n 'detection:complete': { integration: string };\n 'detection:none': Record<string, never>;\n 'git:checking': Record<string, never>;\n 'git:clean': Record<string, never>;\n 'git:dirty': { files: string[] };\n 'git:dirty:confirmed': Record<string, never>;\n 'git:dirty:cancelled': Record<string, never>;\n 'credentials:gathering': { requiresApiKey: boolean };\n 'credentials:found': Record<string, never>;\n // Credential discovery events\n 'credentials:env:detected': { files: string[] };\n 'credentials:env:prompt': { files: string[] };\n 'credentials:env:scanning': Record<string, never>;\n 'credentials:env:found': { sourcePath: string };\n 'credentials:env:notfound': Record<string, never>;\n // Device auth events\n 'device:started': { verificationUri: string; verificationUriComplete: string; userCode: string };\n 'device:polling': Record<string, never>;\n 'device:success': { email?: string };\n 'device:timeout': Record<string, never>;\n 'device:error': { message: string };\n // Staging API events\n 'staging:fetching': Record<string, never>;\n 'staging:success': Record<string, never>;\n 'staging:error': { message: string; statusCode?: number };\n 'config:start': Record<string, never>;\n 'config:complete': Record<string, never>;\n 'agent:start': Record<string, never>;\n 'agent:progress': { step: string; detail?: string };\n 'agent:success': { summary?: string };\n 'agent:failure': { message: string; stack?: string };\n 'agent:retry': { attempt: number; maxRetries: number };\n\n 'validation:retry:start': { attempt: number };\n 'validation:retry:complete': { attempt: number; passed: boolean };\n\n 'validation:start': { framework: string };\n 'validation:issues': { issues: import('./validation/types.js').ValidationIssue[] };\n 'validation:complete': { passed: boolean; issueCount: number; durationMs: number };\n\n // Scaffold events (empty-directory app scaffolding)\n 'scaffold:checking': Record<string, never>;\n 'scaffold:prompt': { packageManager: string };\n 'scaffold:start': { packageManager: string };\n 'scaffold:progress': { text: string };\n 'scaffold:complete': Record<string, never>;\n 'scaffold:failed': { error: string };\n 'scaffold:skipped': Record<string, never>;\n\n // Branch check events\n 'branch:checking': Record<string, never>;\n 'branch:protected': { branch: string };\n 'branch:prompt': { branch: string };\n 'branch:created': { branch: string };\n 'branch:create:failed': { error: string };\n 'branch:skipped': Record<string, never>;\n\n // Post-install events\n 'postinstall:changes': { files: string[] };\n 'postinstall:nochanges': Record<string, never>;\n 'postinstall:commit:prompt': Record<string, never>;\n 'postinstall:commit:generating': Record<string, never>;\n 'postinstall:commit:committing': { message: string };\n 'postinstall:commit:success': { message: string };\n 'postinstall:commit:failed': { error: string };\n 'postinstall:pr:prompt': Record<string, never>;\n 'postinstall:pr:generating': Record<string, never>;\n 'postinstall:pr:pushing': Record<string, never>;\n 'postinstall:pr:creating': Record<string, never>;\n 'postinstall:pr:success': { url: string };\n 'postinstall:pr:failed': { error: string };\n 'postinstall:push:failed': { error: string };\n 'postinstall:manual': { instructions: string };\n}\n\nexport type InstallerEventName = keyof InstallerEvents;\n\nexport class InstallerEventEmitter extends EventEmitter {\n emit<K extends InstallerEventName>(event: K, payload: InstallerEvents[K]): boolean {\n return super.emit(event, payload);\n }\n\n on<K extends InstallerEventName>(event: K, listener: (payload: InstallerEvents[K]) => void): this {\n return super.on(event, listener);\n }\n\n off<K extends InstallerEventName>(event: K, listener: (payload: InstallerEvents[K]) => void): this {\n return super.off(event, listener);\n }\n\n once<K extends InstallerEventName>(event: K, listener: (payload: InstallerEvents[K]) => void): this {\n return super.once(event, listener);\n }\n}\n\nexport function createInstallerEventEmitter(): InstallerEventEmitter {\n return new InstallerEventEmitter();\n}\n"]}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/lib/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAiItC,MAAM,OAAO,qBAAsB,SAAQ,YAAY;IACrD,IAAI,CAA+B,KAAQ,EAAE,OAA2B;QACtE,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,EAAE,CAA+B,KAAQ,EAAE,QAA+C;QACxF,OAAO,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,GAAG,CAA+B,KAAQ,EAAE,QAA+C;QACzF,OAAO,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,CAA+B,KAAQ,EAAE,QAA+C;QAC1F,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC;CACF;AAED,MAAM,UAAU,2BAA2B;IACzC,OAAO,IAAI,qBAAqB,EAAE,CAAC;AACrC,CAAC","sourcesContent":["import { EventEmitter } from 'events';\n\n/**\n * Structured data describing a successful installation, used to render the\n * completion summary and enrich the headless `complete` NDJSON event.\n *\n * Defined here (not in installer-core.types.ts) to avoid an import cycle:\n * installer-core.types.ts already imports from this module, so this module\n * must not import back.\n */\nexport interface CompletionData {\n /** Integration identifier (e.g. 'nextjs') */\n integration: string;\n /** Lockfile-aware dev command, e.g. \"pnpm run dev\" */\n devCommand: string;\n /** App URL with the detected port, e.g. \"http://localhost:3000\" */\n url: string;\n /** Changed files (git-relative), full list — display cap lives in the renderer */\n files: string[];\n /** Composed concrete + framework next-step lines */\n nextSteps: string[];\n /** Per-framework docs URL */\n docsUrl: string;\n /** WorkOS dashboard URL */\n dashboardUrl: string;\n /** Optional per-framework \"add a sign-in link\" snippet */\n signInSnippet?: string;\n}\n\nexport interface InstallerEvents {\n status: { message: string };\n output: { text: string; isError?: boolean };\n 'file:write': { path: string; content: string };\n 'file:edit': { path: string; oldContent: string; newContent: string };\n 'prompt:request': { id: string; message: string; options?: string[] };\n 'prompt:response': { id: string; value: string };\n 'confirm:request': { id: string; message: string; warning?: string; files?: string[] };\n 'confirm:response': { id: string; confirmed: boolean };\n 'credentials:request': { requiresApiKey: boolean };\n 'credentials:response': { apiKey: string; clientId: string };\n complete: { success: boolean; summary?: string; completion?: CompletionData };\n error: { message: string; stack?: string };\n\n 'state:enter': { state: string };\n 'state:exit': { state: string };\n 'auth:checking': Record<string, never>;\n 'auth:required': Record<string, never>;\n 'auth:success': Record<string, never>;\n 'auth:failure': { message: string };\n 'detection:start': Record<string, never>;\n 'detection:complete': { integration: string };\n 'detection:none': Record<string, never>;\n 'git:checking': Record<string, never>;\n 'git:clean': Record<string, never>;\n 'git:dirty': { files: string[] };\n 'git:dirty:confirmed': Record<string, never>;\n 'git:dirty:cancelled': Record<string, never>;\n 'credentials:gathering': { requiresApiKey: boolean };\n 'credentials:found': Record<string, never>;\n // Credential discovery events\n 'credentials:env:detected': { files: string[] };\n 'credentials:env:prompt': { files: string[] };\n 'credentials:env:scanning': Record<string, never>;\n 'credentials:env:found': { sourcePath: string };\n 'credentials:env:notfound': Record<string, never>;\n // Device auth events\n 'device:started': { verificationUri: string; verificationUriComplete: string; userCode: string };\n 'device:polling': Record<string, never>;\n 'device:success': { email?: string };\n 'device:timeout': Record<string, never>;\n 'device:error': { message: string };\n // Staging API events\n 'staging:fetching': Record<string, never>;\n 'staging:success': { source?: 'device' | 'stored' };\n 'staging:error': { message: string; statusCode?: number };\n 'config:start': Record<string, never>;\n 'config:complete': Record<string, never>;\n 'agent:start': Record<string, never>;\n 'agent:progress': { step: string; detail?: string };\n 'agent:success': { summary?: string };\n 'agent:failure': { message: string; stack?: string };\n 'agent:retry': { attempt: number; maxRetries: number };\n // Surfaced agent tool activity (e.g. Bash commands run during install)\n 'agent:tool': { kind: 'command'; detail: string };\n\n 'validation:retry:start': { attempt: number };\n 'validation:retry:complete': { attempt: number; passed: boolean };\n\n 'validation:start': { framework: string };\n 'validation:issues': { issues: import('./validation/types.js').ValidationIssue[] };\n 'validation:complete': { passed: boolean; issueCount: number; durationMs: number };\n\n // Scaffold events (empty-directory app scaffolding)\n 'scaffold:checking': Record<string, never>;\n 'scaffold:prompt': { packageManager: string };\n 'scaffold:start': { packageManager: string };\n 'scaffold:progress': { text: string };\n 'scaffold:complete': Record<string, never>;\n 'scaffold:failed': { error: string };\n 'scaffold:skipped': Record<string, never>;\n\n // Branch check events\n 'branch:checking': Record<string, never>;\n 'branch:protected': { branch: string };\n 'branch:prompt': { branch: string };\n 'branch:created': { branch: string };\n 'branch:create:failed': { error: string };\n 'branch:skipped': Record<string, never>;\n\n // Post-install events\n 'postinstall:changes': { files: string[] };\n 'postinstall:nochanges': Record<string, never>;\n 'postinstall:commit:prompt': Record<string, never>;\n 'postinstall:commit:generating': Record<string, never>;\n 'postinstall:commit:committing': { message: string };\n 'postinstall:commit:success': { message: string };\n 'postinstall:commit:failed': { error: string };\n 'postinstall:pr:prompt': Record<string, never>;\n 'postinstall:pr:generating': Record<string, never>;\n 'postinstall:pr:pushing': Record<string, never>;\n 'postinstall:pr:creating': Record<string, never>;\n 'postinstall:pr:success': { url: string };\n 'postinstall:pr:failed': { error: string };\n 'postinstall:push:failed': { error: string };\n 'postinstall:manual': { instructions: string };\n}\n\nexport type InstallerEventName = keyof InstallerEvents;\n\nexport class InstallerEventEmitter extends EventEmitter {\n emit<K extends InstallerEventName>(event: K, payload: InstallerEvents[K]): boolean {\n return super.emit(event, payload);\n }\n\n on<K extends InstallerEventName>(event: K, listener: (payload: InstallerEvents[K]) => void): this {\n return super.on(event, listener);\n }\n\n off<K extends InstallerEventName>(event: K, listener: (payload: InstallerEvents[K]) => void): this {\n return super.off(event, listener);\n }\n\n once<K extends InstallerEventName>(event: K, listener: (payload: InstallerEvents[K]) => void): this {\n return super.once(event, listener);\n }\n}\n\nexport function createInstallerEventEmitter(): InstallerEventEmitter {\n return new InstallerEventEmitter();\n}\n"]}
@@ -116,6 +116,12 @@ export interface UIConfig {
116
116
  getOutroChanges: (context: any) => string[];
117
117
  /** Generate "Next steps" bullets from context */
118
118
  getOutroNextSteps: (context: any) => string[];
119
+ /**
120
+ * Optional per-framework "add a sign-in link" snippet, surfaced as a next
121
+ * step in the completion summary. Only defined for frameworks that scaffold
122
+ * interactive auth UI. Copy must stay accurate to what the agent scaffolds.
123
+ */
124
+ getSignInSnippet?: (context: any) => string;
119
125
  }
120
126
  /**
121
127
  * Generate welcome message from framework name
@@ -1 +1 @@
1
- {"version":3,"file":"framework-config.js","sourceRoot":"","sources":["../../src/lib/framework-config.ts"],"names":[],"mappings":"AAmJA;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,aAAqB;IACrD,OAAO,kBAAkB,aAAa,4BAA4B,CAAC;AACrE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,iFAAiF,CAAC","sourcesContent":["import type { InstallerOptions } from '../utils/types.js';\n\n/**\n * Supported programming languages for framework integrations.\n */\nexport type Language = 'javascript' | 'python' | 'ruby' | 'php' | 'go' | 'kotlin' | 'dotnet' | 'elixir';\n\n/**\n * Configuration interface for framework-specific agent integrations.\n * Each framework exports a FrameworkConfig that the universal runner uses.\n */\nexport interface FrameworkConfig {\n metadata: FrameworkMetadata;\n detection: FrameworkDetection;\n environment: EnvironmentConfig;\n analytics: AnalyticsConfig;\n prompts: PromptConfig;\n ui: UIConfig;\n}\n\n/**\n * Basic framework information and documentation\n */\nexport interface FrameworkMetadata {\n /** Display name (e.g., \"Next.js\", \"React\") */\n name: string;\n\n /** Integration identifier (e.g., 'nextjs', 'python'). String, not enum — auto-discovered from registry. */\n integration: string;\n\n /** URL to framework-specific WorkOS AuthKit docs */\n docsUrl: string;\n\n /**\n * Optional URL to docs for users with unsupported framework versions.\n * If not provided, defaults to docsUrl.\n */\n unsupportedVersionDocsUrl?: string;\n\n /**\n * Optional function to gather framework-specific context before agent runs.\n * For Next.js: detects router type\n * For React Native: detects Expo vs bare\n */\n gatherContext?: (options: InstallerOptions) => Promise<Record<string, any>>;\n\n /**\n * Name of the framework-specific skill for agent integration.\n * Skills are located in .claude/skills/{skillName}/SKILL.md\n */\n skillName?: string;\n\n /** Language ecosystem this integration belongs to */\n language: Language;\n\n /** Stability tier: 'stable' for tested integrations, 'experimental' for new ones */\n stability: 'stable' | 'experimental';\n\n /** Detection priority — higher numbers are checked first */\n priority: number;\n\n /** Default package manager command (e.g., 'pip', 'gem', 'go'). Optional for JS integrations. */\n packageManager?: string;\n\n /** Primary manifest file (e.g., 'pyproject.toml', 'Gemfile'). Optional for JS integrations. */\n manifestFile?: string;\n\n /**\n * Optional custom detection override for non-JS integrations. When present,\n * the registry calls this instead of falling back to `manifestFile` existence.\n * Use when a single manifest file isn't enough (e.g., Django projects may\n * use `manage.py` + `requirements.txt` without a `pyproject.toml`).\n */\n detect?: (options: Pick<InstallerOptions, 'installDir'>) => boolean | Promise<boolean>;\n}\n\n/**\n * Framework detection and version handling\n */\nexport interface FrameworkDetection {\n /** Package name to check in package.json (e.g., \"next\", \"react\") */\n packageName: string;\n\n /** Human-readable name for error messages (e.g., \"Next.js\") */\n packageDisplayName: string;\n\n /** Extract version from package.json */\n getVersion: (packageJson: any) => string | undefined;\n\n /** Optional: Convert version to analytics bucket (e.g., \"15.x\") */\n getVersionBucket?: (version: string) => string;\n}\n\n/**\n * Environment variable configuration\n */\nexport interface EnvironmentConfig {\n /** Whether to upload env vars to hosting providers post-agent */\n uploadToHosting: boolean;\n\n /** Whether this framework requires API key (false for client-only SDKs) */\n requiresApiKey: boolean;\n\n /**\n * Build the environment variables object for this framework.\n * Returns the exact variable names and values to upload to hosting providers.\n */\n getEnvVars: (apiKey: string, clientId: string) => Record<string, string>;\n}\n\n/**\n * Analytics configuration\n */\nexport interface AnalyticsConfig {\n /** Generate tags from context (e.g., { 'nextjs-version': '15.x', 'router': 'app' }) */\n getTags: (context: any) => Record<string, any>;\n\n /** Optional: Additional event properties */\n getEventProperties?: (context: any) => Record<string, any>;\n}\n\n/**\n * Prompt configuration\n */\nexport interface PromptConfig {\n /**\n * Optional: Additional context lines to append to base prompt\n * For Next.js: \"- Router: app\"\n * For React Native: \"- Platform: Expo\"\n */\n getAdditionalContextLines?: (context: any) => string[];\n}\n\n/**\n * UI messaging configuration\n */\nexport interface UIConfig {\n /** Success message when agent completes */\n successMessage: string;\n\n /** Generate \"What the agent did\" bullets from context */\n getOutroChanges: (context: any) => string[];\n\n /** Generate \"Next steps\" bullets from context */\n getOutroNextSteps: (context: any) => string[];\n}\n\n/**\n * Generate welcome message from framework name\n */\nexport function getWelcomeMessage(frameworkName: string): string {\n return `WorkOS AuthKit ${frameworkName} installer (agent-powered)`;\n}\n\n/**\n * Shared spinner message for all frameworks\n */\nexport const SPINNER_MESSAGE = 'Setting up WorkOS AuthKit with login, authentication, and session management...';\n"]}
1
+ {"version":3,"file":"framework-config.js","sourceRoot":"","sources":["../../src/lib/framework-config.ts"],"names":[],"mappings":"AA0JA;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,aAAqB;IACrD,OAAO,kBAAkB,aAAa,4BAA4B,CAAC;AACrE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,iFAAiF,CAAC","sourcesContent":["import type { InstallerOptions } from '../utils/types.js';\n\n/**\n * Supported programming languages for framework integrations.\n */\nexport type Language = 'javascript' | 'python' | 'ruby' | 'php' | 'go' | 'kotlin' | 'dotnet' | 'elixir';\n\n/**\n * Configuration interface for framework-specific agent integrations.\n * Each framework exports a FrameworkConfig that the universal runner uses.\n */\nexport interface FrameworkConfig {\n metadata: FrameworkMetadata;\n detection: FrameworkDetection;\n environment: EnvironmentConfig;\n analytics: AnalyticsConfig;\n prompts: PromptConfig;\n ui: UIConfig;\n}\n\n/**\n * Basic framework information and documentation\n */\nexport interface FrameworkMetadata {\n /** Display name (e.g., \"Next.js\", \"React\") */\n name: string;\n\n /** Integration identifier (e.g., 'nextjs', 'python'). String, not enum — auto-discovered from registry. */\n integration: string;\n\n /** URL to framework-specific WorkOS AuthKit docs */\n docsUrl: string;\n\n /**\n * Optional URL to docs for users with unsupported framework versions.\n * If not provided, defaults to docsUrl.\n */\n unsupportedVersionDocsUrl?: string;\n\n /**\n * Optional function to gather framework-specific context before agent runs.\n * For Next.js: detects router type\n * For React Native: detects Expo vs bare\n */\n gatherContext?: (options: InstallerOptions) => Promise<Record<string, any>>;\n\n /**\n * Name of the framework-specific skill for agent integration.\n * Skills are located in .claude/skills/{skillName}/SKILL.md\n */\n skillName?: string;\n\n /** Language ecosystem this integration belongs to */\n language: Language;\n\n /** Stability tier: 'stable' for tested integrations, 'experimental' for new ones */\n stability: 'stable' | 'experimental';\n\n /** Detection priority — higher numbers are checked first */\n priority: number;\n\n /** Default package manager command (e.g., 'pip', 'gem', 'go'). Optional for JS integrations. */\n packageManager?: string;\n\n /** Primary manifest file (e.g., 'pyproject.toml', 'Gemfile'). Optional for JS integrations. */\n manifestFile?: string;\n\n /**\n * Optional custom detection override for non-JS integrations. When present,\n * the registry calls this instead of falling back to `manifestFile` existence.\n * Use when a single manifest file isn't enough (e.g., Django projects may\n * use `manage.py` + `requirements.txt` without a `pyproject.toml`).\n */\n detect?: (options: Pick<InstallerOptions, 'installDir'>) => boolean | Promise<boolean>;\n}\n\n/**\n * Framework detection and version handling\n */\nexport interface FrameworkDetection {\n /** Package name to check in package.json (e.g., \"next\", \"react\") */\n packageName: string;\n\n /** Human-readable name for error messages (e.g., \"Next.js\") */\n packageDisplayName: string;\n\n /** Extract version from package.json */\n getVersion: (packageJson: any) => string | undefined;\n\n /** Optional: Convert version to analytics bucket (e.g., \"15.x\") */\n getVersionBucket?: (version: string) => string;\n}\n\n/**\n * Environment variable configuration\n */\nexport interface EnvironmentConfig {\n /** Whether to upload env vars to hosting providers post-agent */\n uploadToHosting: boolean;\n\n /** Whether this framework requires API key (false for client-only SDKs) */\n requiresApiKey: boolean;\n\n /**\n * Build the environment variables object for this framework.\n * Returns the exact variable names and values to upload to hosting providers.\n */\n getEnvVars: (apiKey: string, clientId: string) => Record<string, string>;\n}\n\n/**\n * Analytics configuration\n */\nexport interface AnalyticsConfig {\n /** Generate tags from context (e.g., { 'nextjs-version': '15.x', 'router': 'app' }) */\n getTags: (context: any) => Record<string, any>;\n\n /** Optional: Additional event properties */\n getEventProperties?: (context: any) => Record<string, any>;\n}\n\n/**\n * Prompt configuration\n */\nexport interface PromptConfig {\n /**\n * Optional: Additional context lines to append to base prompt\n * For Next.js: \"- Router: app\"\n * For React Native: \"- Platform: Expo\"\n */\n getAdditionalContextLines?: (context: any) => string[];\n}\n\n/**\n * UI messaging configuration\n */\nexport interface UIConfig {\n /** Success message when agent completes */\n successMessage: string;\n\n /** Generate \"What the agent did\" bullets from context */\n getOutroChanges: (context: any) => string[];\n\n /** Generate \"Next steps\" bullets from context */\n getOutroNextSteps: (context: any) => string[];\n\n /**\n * Optional per-framework \"add a sign-in link\" snippet, surfaced as a next\n * step in the completion summary. Only defined for frameworks that scaffold\n * interactive auth UI. Copy must stay accurate to what the agent scaffolds.\n */\n getSignInSnippet?: (context: any) => string;\n}\n\n/**\n * Generate welcome message from framework name\n */\nexport function getWelcomeMessage(frameworkName: string): string {\n return `WorkOS AuthKit ${frameworkName} installer (agent-powered)`;\n}\n\n/**\n * Shared spinner message for all frameworks\n */\nexport const SPINNER_MESSAGE = 'Setting up WorkOS AuthKit with login, authentication, and session management...';\n"]}
@@ -1,6 +1,7 @@
1
1
  import { type ActorRefFrom } from 'xstate';
2
2
  import type { InstallerMachineContext, InstallerMachineInput, DetectionOutput, GitCheckOutput, AgentOutput, EnvFileInfo, DiscoveryResult, BranchCheckOutput, WorkspaceCheckOutput } from './installer-core.types.js';
3
3
  import type { InstallerOptions } from '../utils/types.js';
4
+ import type { CompletionData } from './events.js';
4
5
  import type { DeviceAuthResult, DeviceAuthResponse } from './device-auth.js';
5
6
  import type { StagingCredentials } from './staging-api.js';
6
7
  export declare const installerMachine: import("xstate").StateMachine<InstallerMachineContext, {
@@ -56,6 +57,8 @@ export declare const installerMachine: import("xstate").StateMachine<InstallerMa
56
57
  context: InstallerMachineContext;
57
58
  }, import("xstate").EventObject> | import("xstate").PromiseActorLogic<AgentOutput, {
58
59
  context: InstallerMachineContext;
60
+ }, import("xstate").EventObject> | import("xstate").PromiseActorLogic<CompletionData | undefined, {
61
+ context: InstallerMachineContext;
59
62
  }, import("xstate").EventObject> | import("xstate").PromiseActorLogic<EnvFileInfo, {
60
63
  installDir: string;
61
64
  }, import("xstate").EventObject> | import("xstate").PromiseActorLogic<DiscoveryResult, {
@@ -142,6 +145,12 @@ export declare const installerMachine: import("xstate").StateMachine<InstallerMa
142
145
  context: InstallerMachineContext;
143
146
  }, import("xstate").EventObject>;
144
147
  id: string | undefined;
148
+ } | {
149
+ src: "buildCompletion";
150
+ logic: import("xstate").PromiseActorLogic<CompletionData | undefined, {
151
+ context: InstallerMachineContext;
152
+ }, import("xstate").EventObject>;
153
+ id: string | undefined;
145
154
  } | {
146
155
  src: "detectEnvFiles";
147
156
  logic: import("xstate").PromiseActorLogic<EnvFileInfo, {
@@ -442,6 +451,9 @@ export declare const installerMachine: import("xstate").StateMachine<InstallerMa
442
451
  } | {
443
452
  type: "emitComplete";
444
453
  params: unknown;
454
+ } | {
455
+ type: "assignCompletion";
456
+ params: unknown;
445
457
  }, {
446
458
  type: "shouldSkipAuth";
447
459
  params: unknown;
@@ -466,7 +478,7 @@ export declare const installerMachine: import("xstate").StateMachine<InstallerMa
466
478
  } | {
467
479
  type: "shouldAutoScaffold";
468
480
  params: unknown;
469
- }, never, "error" | "cancelled" | "complete" | "idle" | "authenticating" | "configuring" | "runningAgent" | {
481
+ }, never, "cancelled" | "error" | "complete" | "idle" | "authenticating" | "configuring" | "runningAgent" | "buildingCompletion" | {
470
482
  scaffold: "done" | "checking" | "running" | "prompting";
471
483
  } | {
472
484
  preparing: {
@@ -547,6 +559,7 @@ export declare const installerMachine: import("xstate").StateMachine<InstallerMa
547
559
  readonly done: {};
548
560
  };
549
561
  };
562
+ readonly buildingCompletion: {};
550
563
  readonly complete: {};
551
564
  readonly cancelled: {};
552
565
  readonly error: {};
@@ -1,6 +1,7 @@
1
1
  import { setup, assign, fromPromise } from 'xstate';
2
2
  import { getManualPrInstructions } from './post-install.js';
3
3
  import { hasGhCli } from '../utils/git-utils.js';
4
+ import { formatWorkOSCommand } from '../utils/command-invocation.js';
4
5
  export const installerMachine = setup({
5
6
  types: {
6
7
  context: {},
@@ -146,7 +147,7 @@ export const installerMachine = setup({
146
147
  context.emitter.emit('staging:fetching', {});
147
148
  },
148
149
  emitStagingSuccess: ({ context }) => {
149
- context.emitter.emit('staging:success', {});
150
+ context.emitter.emit('staging:success', { source: context.deviceAuth ? 'device' : 'stored' });
150
151
  },
151
152
  emitStagingError: ({ context }) => {
152
153
  const message = context.error?.message ?? 'Failed to fetch staging credentials';
@@ -291,8 +292,11 @@ export const installerMachine = setup({
291
292
  },
292
293
  emitComplete: ({ context }) => {
293
294
  const summary = context.agentSummary ?? 'WorkOS AuthKit installed successfully!';
294
- context.emitter.emit('complete', { success: true, summary });
295
+ context.emitter.emit('complete', { success: true, summary, completion: context.completion });
295
296
  },
297
+ assignCompletion: assign({
298
+ completion: ({ event }) => event.output,
299
+ }),
296
300
  },
297
301
  guards: {
298
302
  shouldSkipAuth: ({ context }) => context.options.skipAuth === true,
@@ -331,6 +335,9 @@ export const installerMachine = setup({
331
335
  runAgent: fromPromise(async () => {
332
336
  throw new Error('runAgent not implemented - provide via machine.provide()');
333
337
  }),
338
+ buildCompletion: fromPromise(async () => {
339
+ throw new Error('buildCompletion not implemented - provide via machine.provide()');
340
+ }),
334
341
  // Credential discovery actors
335
342
  detectEnvFiles: fromPromise(async () => {
336
343
  throw new Error('detectEnvFiles not implemented - provide via machine.provide()');
@@ -667,7 +674,7 @@ export const installerMachine = setup({
667
674
  `Because this directory isn't empty, a new app wasn't scaffolded, and no recognized ` +
668
675
  `framework (such as a package.json with Next.js) was found to install into.\n\n` +
669
676
  `Next steps:\n` +
670
- ` - New app: run \`workos install\` in an empty directory to scaffold Next.js + AuthKit.\n` +
677
+ ` - New app: run \`${formatWorkOSCommand('install')}\` in an empty directory to scaffold Next.js + AuthKit.\n` +
671
678
  ` - Existing project: run from the directory that contains your package.json, or pass --install-dir <path>.`);
672
679
  },
673
680
  }),
@@ -950,7 +957,7 @@ export const installerMachine = setup({
950
957
  checking: {
951
958
  always: [
952
959
  {
953
- target: '#installer.complete',
960
+ target: '#installer.buildingCompletion',
954
961
  guard: 'shouldSkipPostInstall',
955
962
  },
956
963
  { target: 'detectingChanges' },
@@ -1095,7 +1102,19 @@ export const installerMachine = setup({
1095
1102
  },
1096
1103
  },
1097
1104
  onDone: {
1098
- target: 'complete',
1105
+ target: 'buildingCompletion',
1106
+ },
1107
+ },
1108
+ // Compute the structured completion payload before entering `complete`.
1109
+ // `emitComplete` is a synchronous entry action, but the builder is async
1110
+ // (lockfile-aware dev command, port detection), so it must run in an actor
1111
+ // first. Errors never block completion — they fall through to the static box.
1112
+ buildingCompletion: {
1113
+ invoke: {
1114
+ src: 'buildCompletion',
1115
+ input: ({ context }) => ({ context }),
1116
+ onDone: { target: 'complete', actions: ['assignCompletion'] },
1117
+ onError: { target: 'complete' },
1099
1118
  },
1100
1119
  },
1101
1120
  complete: {