@atlasauth/cli 0.24.0 → 0.25.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 (530) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +4 -4
  3. package/dist/args.d.ts +0 -601
  4. package/dist/args.js +0 -289
  5. package/dist/args.js.map +0 -1
  6. package/dist/cli.d.ts +0 -2
  7. package/dist/cli.js +0 -19
  8. package/dist/cli.js.map +0 -1
  9. package/dist/commands/actions-gallery.d.ts +0 -8
  10. package/dist/commands/actions-gallery.js +0 -197
  11. package/dist/commands/actions-gallery.js.map +0 -1
  12. package/dist/commands/actions.d.ts +0 -13
  13. package/dist/commands/actions.js +0 -135
  14. package/dist/commands/actions.js.map +0 -1
  15. package/dist/commands/admin.d.ts +0 -49
  16. package/dist/commands/admin.js +0 -353
  17. package/dist/commands/admin.js.map +0 -1
  18. package/dist/commands/api-keys.d.ts +0 -4
  19. package/dist/commands/api-keys.js +0 -96
  20. package/dist/commands/api-keys.js.map +0 -1
  21. package/dist/commands/auth.d.ts +0 -25
  22. package/dist/commands/auth.js +0 -102
  23. package/dist/commands/auth.js.map +0 -1
  24. package/dist/commands/config.d.ts +0 -104
  25. package/dist/commands/config.js +0 -1506
  26. package/dist/commands/config.js.map +0 -1
  27. package/dist/commands/csp.d.ts +0 -32
  28. package/dist/commands/csp.js +0 -180
  29. package/dist/commands/csp.js.map +0 -1
  30. package/dist/commands/dev.d.ts +0 -8
  31. package/dist/commands/dev.js +0 -84
  32. package/dist/commands/dev.js.map +0 -1
  33. package/dist/commands/fga.d.ts +0 -10
  34. package/dist/commands/fga.js +0 -146
  35. package/dist/commands/fga.js.map +0 -1
  36. package/dist/commands/golive.d.ts +0 -40
  37. package/dist/commands/golive.js +0 -285
  38. package/dist/commands/golive.js.map +0 -1
  39. package/dist/commands/id-accounts.d.ts +0 -13
  40. package/dist/commands/id-accounts.js +0 -195
  41. package/dist/commands/id-accounts.js.map +0 -1
  42. package/dist/commands/import-better-auth.d.ts +0 -3
  43. package/dist/commands/import-better-auth.js +0 -164
  44. package/dist/commands/import-better-auth.js.map +0 -1
  45. package/dist/commands/import.d.ts +0 -3
  46. package/dist/commands/import.js +0 -123
  47. package/dist/commands/import.js.map +0 -1
  48. package/dist/commands/info.d.ts +0 -75
  49. package/dist/commands/info.js +0 -362
  50. package/dist/commands/info.js.map +0 -1
  51. package/dist/commands/init.d.ts +0 -3
  52. package/dist/commands/init.js +0 -438
  53. package/dist/commands/init.js.map +0 -1
  54. package/dist/commands/integrations.d.ts +0 -8
  55. package/dist/commands/integrations.js +0 -112
  56. package/dist/commands/integrations.js.map +0 -1
  57. package/dist/commands/listen.d.ts +0 -17
  58. package/dist/commands/listen.js +0 -223
  59. package/dist/commands/listen.js.map +0 -1
  60. package/dist/commands/mcp.d.ts +0 -38
  61. package/dist/commands/mcp.js +0 -111
  62. package/dist/commands/mcp.js.map +0 -1
  63. package/dist/commands/migrate.d.ts +0 -16
  64. package/dist/commands/migrate.js +0 -114
  65. package/dist/commands/migrate.js.map +0 -1
  66. package/dist/commands/move-origin.d.ts +0 -11
  67. package/dist/commands/move-origin.js +0 -95
  68. package/dist/commands/move-origin.js.map +0 -1
  69. package/dist/commands/operator.d.ts +0 -18
  70. package/dist/commands/operator.js +0 -238
  71. package/dist/commands/operator.js.map +0 -1
  72. package/dist/commands/orgs.d.ts +0 -4
  73. package/dist/commands/orgs.js +0 -72
  74. package/dist/commands/orgs.js.map +0 -1
  75. package/dist/commands/pages.d.ts +0 -14
  76. package/dist/commands/pages.js +0 -113
  77. package/dist/commands/pages.js.map +0 -1
  78. package/dist/commands/partner-platforms.d.ts +0 -10
  79. package/dist/commands/partner-platforms.js +0 -157
  80. package/dist/commands/partner-platforms.js.map +0 -1
  81. package/dist/commands/project-commands.d.ts +0 -38
  82. package/dist/commands/project-commands.js +0 -361
  83. package/dist/commands/project-commands.js.map +0 -1
  84. package/dist/commands/referrals.d.ts +0 -69
  85. package/dist/commands/referrals.js +0 -1056
  86. package/dist/commands/referrals.js.map +0 -1
  87. package/dist/commands/resources.d.ts +0 -44
  88. package/dist/commands/resources.js +0 -234
  89. package/dist/commands/resources.js.map +0 -1
  90. package/dist/commands/sessions.d.ts +0 -4
  91. package/dist/commands/sessions.js +0 -28
  92. package/dist/commands/sessions.js.map +0 -1
  93. package/dist/commands/shared.d.ts +0 -38
  94. package/dist/commands/shared.js +0 -69
  95. package/dist/commands/shared.js.map +0 -1
  96. package/dist/commands/status.d.ts +0 -3
  97. package/dist/commands/status.js +0 -77
  98. package/dist/commands/status.js.map +0 -1
  99. package/dist/commands/users.d.ts +0 -4
  100. package/dist/commands/users.js +0 -100
  101. package/dist/commands/users.js.map +0 -1
  102. package/dist/commands/webhooks.d.ts +0 -34
  103. package/dist/commands/webhooks.js +0 -301
  104. package/dist/commands/webhooks.js.map +0 -1
  105. package/dist/config-http.d.ts +0 -29
  106. package/dist/config-http.js +0 -64
  107. package/dist/config-http.js.map +0 -1
  108. package/dist/config.d.ts +0 -64
  109. package/dist/config.js +0 -69
  110. package/dist/config.js.map +0 -1
  111. package/dist/context.d.ts +0 -72
  112. package/dist/context.js +0 -27
  113. package/dist/context.js.map +0 -1
  114. package/dist/define-config.d.ts +0 -9
  115. package/dist/define-config.js +0 -8
  116. package/dist/define-config.js.map +0 -1
  117. package/dist/errors.d.ts +0 -15
  118. package/dist/errors.js +0 -25
  119. package/dist/errors.js.map +0 -1
  120. package/dist/help.d.ts +0 -8
  121. package/dist/help.js +0 -868
  122. package/dist/help.js.map +0 -1
  123. package/dist/import/csv.d.ts +0 -6
  124. package/dist/import/csv.js +0 -63
  125. package/dist/import/csv.js.map +0 -1
  126. package/dist/import/vendors.d.ts +0 -57
  127. package/dist/import/vendors.js +0 -568
  128. package/dist/import/vendors.js.map +0 -1
  129. package/dist/index.d.ts +0 -33
  130. package/dist/index.js +0 -81
  131. package/dist/index.js.map +0 -1
  132. package/dist/io.d.ts +0 -21
  133. package/dist/io.js +0 -28
  134. package/dist/io.js.map +0 -1
  135. package/dist/migrate/appwrite/plugin.d.ts +0 -2
  136. package/dist/migrate/appwrite/plugin.js +0 -103
  137. package/dist/migrate/appwrite/plugin.js.map +0 -1
  138. package/dist/migrate/auth0/plugin.d.ts +0 -2
  139. package/dist/migrate/auth0/plugin.js +0 -126
  140. package/dist/migrate/auth0/plugin.js.map +0 -1
  141. package/dist/migrate/authentik/plugin.d.ts +0 -2
  142. package/dist/migrate/authentik/plugin.js +0 -135
  143. package/dist/migrate/authentik/plugin.js.map +0 -1
  144. package/dist/migrate/azure-ad-b2c/plugin.d.ts +0 -8
  145. package/dist/migrate/azure-ad-b2c/plugin.js +0 -165
  146. package/dist/migrate/azure-ad-b2c/plugin.js.map +0 -1
  147. package/dist/migrate/better-auth/integration.d.ts +0 -59
  148. package/dist/migrate/better-auth/integration.js +0 -81
  149. package/dist/migrate/better-auth/integration.js.map +0 -1
  150. package/dist/migrate/better-auth/orchestrator.d.ts +0 -43
  151. package/dist/migrate/better-auth/orchestrator.js +0 -525
  152. package/dist/migrate/better-auth/orchestrator.js.map +0 -1
  153. package/dist/migrate/better-auth/output.d.ts +0 -20
  154. package/dist/migrate/better-auth/output.js +0 -146
  155. package/dist/migrate/better-auth/output.js.map +0 -1
  156. package/dist/migrate/better-auth/translate.d.ts +0 -77
  157. package/dist/migrate/better-auth/translate.js +0 -1989
  158. package/dist/migrate/better-auth/translate.js.map +0 -1
  159. package/dist/migrate/clerk/plugin.d.ts +0 -2
  160. package/dist/migrate/clerk/plugin.js +0 -76
  161. package/dist/migrate/clerk/plugin.js.map +0 -1
  162. package/dist/migrate/cognito/plugin.d.ts +0 -5
  163. package/dist/migrate/cognito/plugin.js +0 -170
  164. package/dist/migrate/cognito/plugin.js.map +0 -1
  165. package/dist/migrate/corbado/plugin.d.ts +0 -2
  166. package/dist/migrate/corbado/plugin.js +0 -63
  167. package/dist/migrate/corbado/plugin.js.map +0 -1
  168. package/dist/migrate/descope/plugin.d.ts +0 -2
  169. package/dist/migrate/descope/plugin.js +0 -83
  170. package/dist/migrate/descope/plugin.js.map +0 -1
  171. package/dist/migrate/entra-external-id/plugin.d.ts +0 -8
  172. package/dist/migrate/entra-external-id/plugin.js +0 -12
  173. package/dist/migrate/entra-external-id/plugin.js.map +0 -1
  174. package/dist/migrate/export/appwrite-config.d.ts +0 -28
  175. package/dist/migrate/export/appwrite-config.js +0 -170
  176. package/dist/migrate/export/appwrite-config.js.map +0 -1
  177. package/dist/migrate/export/appwrite.d.ts +0 -51
  178. package/dist/migrate/export/appwrite.js +0 -288
  179. package/dist/migrate/export/appwrite.js.map +0 -1
  180. package/dist/migrate/export/auth0-config.d.ts +0 -29
  181. package/dist/migrate/export/auth0-config.js +0 -249
  182. package/dist/migrate/export/auth0-config.js.map +0 -1
  183. package/dist/migrate/export/auth0.d.ts +0 -62
  184. package/dist/migrate/export/auth0.js +0 -575
  185. package/dist/migrate/export/auth0.js.map +0 -1
  186. package/dist/migrate/export/authentik-config.d.ts +0 -45
  187. package/dist/migrate/export/authentik-config.js +0 -357
  188. package/dist/migrate/export/authentik-config.js.map +0 -1
  189. package/dist/migrate/export/authentik.d.ts +0 -110
  190. package/dist/migrate/export/authentik.js +0 -838
  191. package/dist/migrate/export/authentik.js.map +0 -1
  192. package/dist/migrate/export/azure-config.d.ts +0 -58
  193. package/dist/migrate/export/azure-config.js +0 -344
  194. package/dist/migrate/export/azure-config.js.map +0 -1
  195. package/dist/migrate/export/azure.d.ts +0 -85
  196. package/dist/migrate/export/azure.js +0 -373
  197. package/dist/migrate/export/azure.js.map +0 -1
  198. package/dist/migrate/export/clerk-config.d.ts +0 -26
  199. package/dist/migrate/export/clerk-config.js +0 -227
  200. package/dist/migrate/export/clerk-config.js.map +0 -1
  201. package/dist/migrate/export/clerk.d.ts +0 -46
  202. package/dist/migrate/export/clerk.js +0 -486
  203. package/dist/migrate/export/clerk.js.map +0 -1
  204. package/dist/migrate/export/cognito-config.d.ts +0 -25
  205. package/dist/migrate/export/cognito-config.js +0 -273
  206. package/dist/migrate/export/cognito-config.js.map +0 -1
  207. package/dist/migrate/export/cognito.d.ts +0 -103
  208. package/dist/migrate/export/cognito.js +0 -441
  209. package/dist/migrate/export/cognito.js.map +0 -1
  210. package/dist/migrate/export/corbado-config.d.ts +0 -20
  211. package/dist/migrate/export/corbado-config.js +0 -63
  212. package/dist/migrate/export/corbado-config.js.map +0 -1
  213. package/dist/migrate/export/corbado.d.ts +0 -37
  214. package/dist/migrate/export/corbado.js +0 -132
  215. package/dist/migrate/export/corbado.js.map +0 -1
  216. package/dist/migrate/export/descope.d.ts +0 -35
  217. package/dist/migrate/export/descope.js +0 -208
  218. package/dist/migrate/export/descope.js.map +0 -1
  219. package/dist/migrate/export/fake-vendor.test-helper.d.ts +0 -27
  220. package/dist/migrate/export/fake-vendor.test-helper.js +0 -41
  221. package/dist/migrate/export/fake-vendor.test-helper.js.map +0 -1
  222. package/dist/migrate/export/firebase-config.d.ts +0 -24
  223. package/dist/migrate/export/firebase-config.js +0 -215
  224. package/dist/migrate/export/firebase-config.js.map +0 -1
  225. package/dist/migrate/export/firebase.d.ts +0 -102
  226. package/dist/migrate/export/firebase.js +0 -464
  227. package/dist/migrate/export/firebase.js.map +0 -1
  228. package/dist/migrate/export/frameworks/app-users.d.ts +0 -42
  229. package/dist/migrate/export/frameworks/app-users.js +0 -161
  230. package/dist/migrate/export/frameworks/app-users.js.map +0 -1
  231. package/dist/migrate/export/frameworks/authjs.d.ts +0 -41
  232. package/dist/migrate/export/frameworks/authjs.js +0 -146
  233. package/dist/migrate/export/frameworks/authjs.js.map +0 -1
  234. package/dist/migrate/export/frameworks/devise.d.ts +0 -39
  235. package/dist/migrate/export/frameworks/devise.js +0 -218
  236. package/dist/migrate/export/frameworks/devise.js.map +0 -1
  237. package/dist/migrate/export/frameworks/django.d.ts +0 -45
  238. package/dist/migrate/export/frameworks/django.js +0 -315
  239. package/dist/migrate/export/frameworks/django.js.map +0 -1
  240. package/dist/migrate/export/frameworks/lucia.d.ts +0 -42
  241. package/dist/migrate/export/frameworks/lucia.js +0 -263
  242. package/dist/migrate/export/frameworks/lucia.js.map +0 -1
  243. package/dist/migrate/export/frameworks/tables.d.ts +0 -90
  244. package/dist/migrate/export/frameworks/tables.js +0 -325
  245. package/dist/migrate/export/frameworks/tables.js.map +0 -1
  246. package/dist/migrate/export/frameworks/webauthn.d.ts +0 -25
  247. package/dist/migrate/export/frameworks/webauthn.js +0 -130
  248. package/dist/migrate/export/frameworks/webauthn.js.map +0 -1
  249. package/dist/migrate/export/frontegg-config.d.ts +0 -29
  250. package/dist/migrate/export/frontegg-config.js +0 -238
  251. package/dist/migrate/export/frontegg-config.js.map +0 -1
  252. package/dist/migrate/export/frontegg.d.ts +0 -67
  253. package/dist/migrate/export/frontegg.js +0 -410
  254. package/dist/migrate/export/frontegg.js.map +0 -1
  255. package/dist/migrate/export/fusionauth-config.d.ts +0 -26
  256. package/dist/migrate/export/fusionauth-config.js +0 -226
  257. package/dist/migrate/export/fusionauth-config.js.map +0 -1
  258. package/dist/migrate/export/fusionauth.d.ts +0 -99
  259. package/dist/migrate/export/fusionauth.js +0 -642
  260. package/dist/migrate/export/fusionauth.js.map +0 -1
  261. package/dist/migrate/export/hanko-config.d.ts +0 -27
  262. package/dist/migrate/export/hanko-config.js +0 -265
  263. package/dist/migrate/export/hanko-config.js.map +0 -1
  264. package/dist/migrate/export/hanko.d.ts +0 -52
  265. package/dist/migrate/export/hanko.js +0 -605
  266. package/dist/migrate/export/hanko.js.map +0 -1
  267. package/dist/migrate/export/keycloak-config.d.ts +0 -19
  268. package/dist/migrate/export/keycloak-config.js +0 -219
  269. package/dist/migrate/export/keycloak-config.js.map +0 -1
  270. package/dist/migrate/export/keycloak.d.ts +0 -155
  271. package/dist/migrate/export/keycloak.js +0 -878
  272. package/dist/migrate/export/keycloak.js.map +0 -1
  273. package/dist/migrate/export/kinde-descope-config.d.ts +0 -38
  274. package/dist/migrate/export/kinde-descope-config.js +0 -172
  275. package/dist/migrate/export/kinde-descope-config.js.map +0 -1
  276. package/dist/migrate/export/kinde.d.ts +0 -57
  277. package/dist/migrate/export/kinde.js +0 -333
  278. package/dist/migrate/export/kinde.js.map +0 -1
  279. package/dist/migrate/export/ldap.d.ts +0 -53
  280. package/dist/migrate/export/ldap.js +0 -277
  281. package/dist/migrate/export/ldap.js.map +0 -1
  282. package/dist/migrate/export/logto-config.d.ts +0 -27
  283. package/dist/migrate/export/logto-config.js +0 -264
  284. package/dist/migrate/export/logto-config.js.map +0 -1
  285. package/dist/migrate/export/logto.d.ts +0 -150
  286. package/dist/migrate/export/logto.js +0 -809
  287. package/dist/migrate/export/logto.js.map +0 -1
  288. package/dist/migrate/export/magic-config.d.ts +0 -14
  289. package/dist/migrate/export/magic-config.js +0 -28
  290. package/dist/migrate/export/magic-config.js.map +0 -1
  291. package/dist/migrate/export/magic.d.ts +0 -31
  292. package/dist/migrate/export/magic.js +0 -93
  293. package/dist/migrate/export/magic.js.map +0 -1
  294. package/dist/migrate/export/mini-yaml.d.ts +0 -19
  295. package/dist/migrate/export/mini-yaml.js +0 -581
  296. package/dist/migrate/export/mini-yaml.js.map +0 -1
  297. package/dist/migrate/export/nhost-config.d.ts +0 -26
  298. package/dist/migrate/export/nhost-config.js +0 -360
  299. package/dist/migrate/export/nhost-config.js.map +0 -1
  300. package/dist/migrate/export/nhost.d.ts +0 -64
  301. package/dist/migrate/export/nhost.js +0 -304
  302. package/dist/migrate/export/nhost.js.map +0 -1
  303. package/dist/migrate/export/okta-config.d.ts +0 -30
  304. package/dist/migrate/export/okta-config.js +0 -205
  305. package/dist/migrate/export/okta-config.js.map +0 -1
  306. package/dist/migrate/export/okta.d.ts +0 -43
  307. package/dist/migrate/export/okta.js +0 -337
  308. package/dist/migrate/export/okta.js.map +0 -1
  309. package/dist/migrate/export/onelogin.d.ts +0 -22
  310. package/dist/migrate/export/onelogin.js +0 -123
  311. package/dist/migrate/export/onelogin.js.map +0 -1
  312. package/dist/migrate/export/ory-config.d.ts +0 -58
  313. package/dist/migrate/export/ory-config.js +0 -451
  314. package/dist/migrate/export/ory-config.js.map +0 -1
  315. package/dist/migrate/export/ory.d.ts +0 -81
  316. package/dist/migrate/export/ory.js +0 -555
  317. package/dist/migrate/export/ory.js.map +0 -1
  318. package/dist/migrate/export/password-detect.d.ts +0 -29
  319. package/dist/migrate/export/password-detect.js +0 -81
  320. package/dist/migrate/export/password-detect.js.map +0 -1
  321. package/dist/migrate/export/pingone.d.ts +0 -36
  322. package/dist/migrate/export/pingone.js +0 -218
  323. package/dist/migrate/export/pingone.js.map +0 -1
  324. package/dist/migrate/export/plugin-kit.d.ts +0 -25
  325. package/dist/migrate/export/plugin-kit.js +0 -82
  326. package/dist/migrate/export/plugin-kit.js.map +0 -1
  327. package/dist/migrate/export/pocketbase-config.d.ts +0 -28
  328. package/dist/migrate/export/pocketbase-config.js +0 -180
  329. package/dist/migrate/export/pocketbase-config.js.map +0 -1
  330. package/dist/migrate/export/pocketbase.d.ts +0 -52
  331. package/dist/migrate/export/pocketbase.js +0 -243
  332. package/dist/migrate/export/pocketbase.js.map +0 -1
  333. package/dist/migrate/export/project-files.d.ts +0 -15
  334. package/dist/migrate/export/project-files.js +0 -43
  335. package/dist/migrate/export/project-files.js.map +0 -1
  336. package/dist/migrate/export/propelauth-config.d.ts +0 -18
  337. package/dist/migrate/export/propelauth-config.js +0 -58
  338. package/dist/migrate/export/propelauth-config.js.map +0 -1
  339. package/dist/migrate/export/propelauth-harness.test-helper.d.ts +0 -62
  340. package/dist/migrate/export/propelauth-harness.test-helper.js +0 -109
  341. package/dist/migrate/export/propelauth-harness.test-helper.js.map +0 -1
  342. package/dist/migrate/export/propelauth.d.ts +0 -48
  343. package/dist/migrate/export/propelauth.js +0 -255
  344. package/dist/migrate/export/propelauth.js.map +0 -1
  345. package/dist/migrate/export/record-set.d.ts +0 -44
  346. package/dist/migrate/export/record-set.js +0 -98
  347. package/dist/migrate/export/record-set.js.map +0 -1
  348. package/dist/migrate/export/source-lines.d.ts +0 -17
  349. package/dist/migrate/export/source-lines.js +0 -43
  350. package/dist/migrate/export/source-lines.js.map +0 -1
  351. package/dist/migrate/export/sso-metadata.d.ts +0 -47
  352. package/dist/migrate/export/sso-metadata.js +0 -180
  353. package/dist/migrate/export/sso-metadata.js.map +0 -1
  354. package/dist/migrate/export/stytch-config.d.ts +0 -22
  355. package/dist/migrate/export/stytch-config.js +0 -102
  356. package/dist/migrate/export/stytch-config.js.map +0 -1
  357. package/dist/migrate/export/stytch.d.ts +0 -68
  358. package/dist/migrate/export/stytch.js +0 -510
  359. package/dist/migrate/export/stytch.js.map +0 -1
  360. package/dist/migrate/export/supabase-config.d.ts +0 -48
  361. package/dist/migrate/export/supabase-config.js +0 -408
  362. package/dist/migrate/export/supabase-config.js.map +0 -1
  363. package/dist/migrate/export/supabase.d.ts +0 -86
  364. package/dist/migrate/export/supabase.js +0 -524
  365. package/dist/migrate/export/supabase.js.map +0 -1
  366. package/dist/migrate/export/supertokens-config.d.ts +0 -20
  367. package/dist/migrate/export/supertokens-config.js +0 -150
  368. package/dist/migrate/export/supertokens-config.js.map +0 -1
  369. package/dist/migrate/export/supertokens.d.ts +0 -125
  370. package/dist/migrate/export/supertokens.js +0 -464
  371. package/dist/migrate/export/supertokens.js.map +0 -1
  372. package/dist/migrate/export/table.d.ts +0 -35
  373. package/dist/migrate/export/table.js +0 -248
  374. package/dist/migrate/export/table.js.map +0 -1
  375. package/dist/migrate/export/translate-kit.d.ts +0 -46
  376. package/dist/migrate/export/translate-kit.js +0 -148
  377. package/dist/migrate/export/translate-kit.js.map +0 -1
  378. package/dist/migrate/export/userfront-config.d.ts +0 -15
  379. package/dist/migrate/export/userfront-config.js +0 -49
  380. package/dist/migrate/export/userfront-config.js.map +0 -1
  381. package/dist/migrate/export/userfront.d.ts +0 -38
  382. package/dist/migrate/export/userfront.js +0 -189
  383. package/dist/migrate/export/userfront.js.map +0 -1
  384. package/dist/migrate/export/vendor-http.d.ts +0 -46
  385. package/dist/migrate/export/vendor-http.js +0 -138
  386. package/dist/migrate/export/vendor-http.js.map +0 -1
  387. package/dist/migrate/export/workos-config.d.ts +0 -23
  388. package/dist/migrate/export/workos-config.js +0 -125
  389. package/dist/migrate/export/workos-config.js.map +0 -1
  390. package/dist/migrate/export/workos.d.ts +0 -46
  391. package/dist/migrate/export/workos.js +0 -272
  392. package/dist/migrate/export/workos.js.map +0 -1
  393. package/dist/migrate/export/zip.d.ts +0 -8
  394. package/dist/migrate/export/zip.js +0 -66
  395. package/dist/migrate/export/zip.js.map +0 -1
  396. package/dist/migrate/export/zitadel-config.d.ts +0 -37
  397. package/dist/migrate/export/zitadel-config.js +0 -279
  398. package/dist/migrate/export/zitadel-config.js.map +0 -1
  399. package/dist/migrate/export/zitadel.d.ts +0 -82
  400. package/dist/migrate/export/zitadel.js +0 -447
  401. package/dist/migrate/export/zitadel.js.map +0 -1
  402. package/dist/migrate/firebase/plugin.d.ts +0 -2
  403. package/dist/migrate/firebase/plugin.js +0 -152
  404. package/dist/migrate/firebase/plugin.js.map +0 -1
  405. package/dist/migrate/framework/builtins.d.ts +0 -2
  406. package/dist/migrate/framework/builtins.js +0 -52
  407. package/dist/migrate/framework/builtins.js.map +0 -1
  408. package/dist/migrate/framework/commands.d.ts +0 -20
  409. package/dist/migrate/framework/commands.js +0 -58
  410. package/dist/migrate/framework/commands.js.map +0 -1
  411. package/dist/migrate/framework/custom.d.ts +0 -12
  412. package/dist/migrate/framework/custom.js +0 -96
  413. package/dist/migrate/framework/custom.js.map +0 -1
  414. package/dist/migrate/framework/orchestrator.d.ts +0 -113
  415. package/dist/migrate/framework/orchestrator.js +0 -532
  416. package/dist/migrate/framework/orchestrator.js.map +0 -1
  417. package/dist/migrate/framework/plugin.d.ts +0 -167
  418. package/dist/migrate/framework/plugin.js +0 -3
  419. package/dist/migrate/framework/plugin.js.map +0 -1
  420. package/dist/migrate/framework/registry.d.ts +0 -11
  421. package/dist/migrate/framework/registry.js +0 -44
  422. package/dist/migrate/framework/registry.js.map +0 -1
  423. package/dist/migrate/framework/report.d.ts +0 -17
  424. package/dist/migrate/framework/report.js +0 -103
  425. package/dist/migrate/framework/report.js.map +0 -1
  426. package/dist/migrate/frameworks/plugins.d.ts +0 -29
  427. package/dist/migrate/frameworks/plugins.js +0 -402
  428. package/dist/migrate/frameworks/plugins.js.map +0 -1
  429. package/dist/migrate/frameworks/report.d.ts +0 -92
  430. package/dist/migrate/frameworks/report.js +0 -207
  431. package/dist/migrate/frameworks/report.js.map +0 -1
  432. package/dist/migrate/frameworks/translate-js.d.ts +0 -5
  433. package/dist/migrate/frameworks/translate-js.js +0 -503
  434. package/dist/migrate/frameworks/translate-js.js.map +0 -1
  435. package/dist/migrate/frameworks/translate-rails-django.d.ts +0 -3
  436. package/dist/migrate/frameworks/translate-rails-django.js +0 -1391
  437. package/dist/migrate/frameworks/translate-rails-django.js.map +0 -1
  438. package/dist/migrate/frontegg/plugin.d.ts +0 -2
  439. package/dist/migrate/frontegg/plugin.js +0 -78
  440. package/dist/migrate/frontegg/plugin.js.map +0 -1
  441. package/dist/migrate/fusionauth/plugin.d.ts +0 -2
  442. package/dist/migrate/fusionauth/plugin.js +0 -109
  443. package/dist/migrate/fusionauth/plugin.js.map +0 -1
  444. package/dist/migrate/hanko/plugin.d.ts +0 -2
  445. package/dist/migrate/hanko/plugin.js +0 -100
  446. package/dist/migrate/hanko/plugin.js.map +0 -1
  447. package/dist/migrate/keycloak/plugin.d.ts +0 -2
  448. package/dist/migrate/keycloak/plugin.js +0 -148
  449. package/dist/migrate/keycloak/plugin.js.map +0 -1
  450. package/dist/migrate/kinde/plugin.d.ts +0 -2
  451. package/dist/migrate/kinde/plugin.js +0 -105
  452. package/dist/migrate/kinde/plugin.js.map +0 -1
  453. package/dist/migrate/ldap/plugin.d.ts +0 -2
  454. package/dist/migrate/ldap/plugin.js +0 -73
  455. package/dist/migrate/ldap/plugin.js.map +0 -1
  456. package/dist/migrate/logto/plugin.d.ts +0 -2
  457. package/dist/migrate/logto/plugin.js +0 -131
  458. package/dist/migrate/logto/plugin.js.map +0 -1
  459. package/dist/migrate/magic/plugin.d.ts +0 -2
  460. package/dist/migrate/magic/plugin.js +0 -56
  461. package/dist/migrate/magic/plugin.js.map +0 -1
  462. package/dist/migrate/nhost/plugin.d.ts +0 -2
  463. package/dist/migrate/nhost/plugin.js +0 -115
  464. package/dist/migrate/nhost/plugin.js.map +0 -1
  465. package/dist/migrate/oidc/plugin.d.ts +0 -2
  466. package/dist/migrate/oidc/plugin.js +0 -73
  467. package/dist/migrate/oidc/plugin.js.map +0 -1
  468. package/dist/migrate/okta/plugin.d.ts +0 -2
  469. package/dist/migrate/okta/plugin.js +0 -105
  470. package/dist/migrate/okta/plugin.js.map +0 -1
  471. package/dist/migrate/onelogin/plugin.d.ts +0 -2
  472. package/dist/migrate/onelogin/plugin.js +0 -61
  473. package/dist/migrate/onelogin/plugin.js.map +0 -1
  474. package/dist/migrate/ory/plugin.d.ts +0 -2
  475. package/dist/migrate/ory/plugin.js +0 -186
  476. package/dist/migrate/ory/plugin.js.map +0 -1
  477. package/dist/migrate/ping-identity/plugin.d.ts +0 -2
  478. package/dist/migrate/ping-identity/plugin.js +0 -100
  479. package/dist/migrate/ping-identity/plugin.js.map +0 -1
  480. package/dist/migrate/pocketbase/plugin.d.ts +0 -2
  481. package/dist/migrate/pocketbase/plugin.js +0 -99
  482. package/dist/migrate/pocketbase/plugin.js.map +0 -1
  483. package/dist/migrate/propelauth/plugin.d.ts +0 -2
  484. package/dist/migrate/propelauth/plugin.js +0 -65
  485. package/dist/migrate/propelauth/plugin.js.map +0 -1
  486. package/dist/migrate/saml/plugin.d.ts +0 -2
  487. package/dist/migrate/saml/plugin.js +0 -79
  488. package/dist/migrate/saml/plugin.js.map +0 -1
  489. package/dist/migrate/stytch/plugin.d.ts +0 -2
  490. package/dist/migrate/stytch/plugin.js +0 -97
  491. package/dist/migrate/stytch/plugin.js.map +0 -1
  492. package/dist/migrate/supabase/plugin.d.ts +0 -2
  493. package/dist/migrate/supabase/plugin.js +0 -149
  494. package/dist/migrate/supabase/plugin.js.map +0 -1
  495. package/dist/migrate/supertokens/plugin.d.ts +0 -2
  496. package/dist/migrate/supertokens/plugin.js +0 -114
  497. package/dist/migrate/supertokens/plugin.js.map +0 -1
  498. package/dist/migrate/user-table/plugin.d.ts +0 -2
  499. package/dist/migrate/user-table/plugin.js +0 -62
  500. package/dist/migrate/user-table/plugin.js.map +0 -1
  501. package/dist/migrate/userfront/plugin.d.ts +0 -2
  502. package/dist/migrate/userfront/plugin.js +0 -60
  503. package/dist/migrate/userfront/plugin.js.map +0 -1
  504. package/dist/migrate/workos/plugin.d.ts +0 -2
  505. package/dist/migrate/workos/plugin.js +0 -81
  506. package/dist/migrate/workos/plugin.js.map +0 -1
  507. package/dist/migrate/zitadel/plugin.d.ts +0 -2
  508. package/dist/migrate/zitadel/plugin.js +0 -114
  509. package/dist/migrate/zitadel/plugin.js.map +0 -1
  510. package/dist/output.d.ts +0 -41
  511. package/dist/output.js +0 -72
  512. package/dist/output.js.map +0 -1
  513. package/dist/project.d.ts +0 -64
  514. package/dist/project.js +0 -86
  515. package/dist/project.js.map +0 -1
  516. package/dist/prompt.d.ts +0 -15
  517. package/dist/prompt.js +0 -46
  518. package/dist/prompt.js.map +0 -1
  519. package/dist/run.d.ts +0 -12
  520. package/dist/run.js +0 -157
  521. package/dist/run.js.map +0 -1
  522. package/dist/secrets.d.ts +0 -41
  523. package/dist/secrets.js +0 -142
  524. package/dist/secrets.js.map +0 -1
  525. package/dist/serialize.d.ts +0 -30
  526. package/dist/serialize.js +0 -131
  527. package/dist/serialize.js.map +0 -1
  528. package/dist/version.d.ts +0 -7
  529. package/dist/version.js +0 -21
  530. package/dist/version.js.map +0 -1
@@ -1,1056 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.REFERALLI_SYNC_TOPICS = exports.REFERALLI_VERSION = void 0;
4
- exports.pingSkewMs = pingSkewMs;
5
- exports.describeTestLines = describeTestLines;
6
- exports.parseCodeCsv = parseCodeCsv;
7
- exports.appOrigins = appOrigins;
8
- exports.referalliKeyMode = referalliKeyMode;
9
- exports.referalliList = referalliList;
10
- exports.referalliLinkTemplate = referalliLinkTemplate;
11
- exports.webhookScope = webhookScope;
12
- exports.referrals = referrals;
13
- const node_crypto_1 = require("node:crypto");
14
- const referral_conformance_1 = require("@atlasauth/referral-conformance");
15
- const backend_1 = require("@atlasauth/backend");
16
- const args_1 = require("../args");
17
- const errors_1 = require("../errors");
18
- const output_1 = require("../output");
19
- const project_1 = require("../project");
20
- const secrets_1 = require("../secrets");
21
- const project_commands_1 = require("./project-commands");
22
- const shared_1 = require("./shared");
23
- /**
24
- * `atlas referrals connect | backfill | resync | status`: referral attribution from the
25
- * terminal.
26
- *
27
- * `connect --provider referalli` is bring-your-own-key: the Referalli merchant
28
- * key is used for one call (it creates the Atlas connection on Referalli) and
29
- * is never stored or printed. The connection id and secret Referalli returns
30
- * go straight onto the instance; the secret is never printed either.
31
- */
32
- /** The Referalli API version pinned on every call. */
33
- exports.REFERALLI_VERSION = '2026-10-21';
34
- const PROVIDERS = ['referalli', 'webhook'];
35
- /** The retired spelling of the Referalli provider id, flags and environment names, still accepted. */
36
- const LEGACY = {
37
- provider: 'referally',
38
- keyFlag: 'referally-key',
39
- keyFileFlag: 'referally-key-file',
40
- baseUrlEnv: 'REFERALLY_BASE_URL',
41
- apiKeyEnv: 'REFERALLY_API_KEY',
42
- };
43
- const envNoticeShown = new WeakSet();
44
- /**
45
- * One notice naming each old REFERALLY_* environment variable to rename (only
46
- * those in use without their new name set), printed at most once per run.
47
- */
48
- function legacyEnvNotice(ctx) {
49
- if (envNoticeShown.has(ctx))
50
- return;
51
- const renames = [
52
- [LEGACY.baseUrlEnv, 'REFERALLI_BASE_URL'],
53
- [LEGACY.apiKeyEnv, 'REFERALLI_API_KEY'],
54
- ].filter(([old, current]) => ctx.env[old]?.trim() && !ctx.env[current]?.trim());
55
- if (!renames.length)
56
- return;
57
- envNoticeShown.add(ctx);
58
- ctx.io.err(`atlas: rename ${renames.map(([old, current]) => `${old} to ${current}`).join(' and ')} in your environment. The old name still works for now.`);
59
- }
60
- /** Print a one-line notice that an old name was used (stderr, so --json output stays clean). */
61
- function legacyNotice(ctx, old, current) {
62
- ctx.io.err(`atlas: '${old}' is the old name of '${current}'. It still works; use '${current}'.`);
63
- }
64
- /** Read a key from a file, or stdin with '-'. A bare key or a dotenv line. Never printed. */
65
- function readKeyFile(ctx, file, what) {
66
- let text;
67
- try {
68
- text = ctx.readFile(file === '-' ? '/dev/stdin' : file);
69
- }
70
- catch {
71
- throw new errors_1.CliError(`Could not read ${what} from ${file === '-' ? 'stdin' : file}.`);
72
- }
73
- const line = text.split(/\r?\n/).map((l) => l.trim()).find((l) => l && !l.startsWith('#')) ?? '';
74
- const m = /^[A-Za-z_][A-Za-z0-9_]*=(.*)$/.exec(line);
75
- const key = (m ? m[1] : line).trim().replace(/^"(.*)"$/, '$1');
76
- if (!key || /\s/.test(key))
77
- throw new errors_1.CliError(`No ${what} found in ${file === '-' ? 'stdin' : file}.`);
78
- return key;
79
- }
80
- function httpsUrl(raw, flag) {
81
- let u;
82
- try {
83
- u = new URL(raw);
84
- }
85
- catch {
86
- throw new errors_1.CliError(`${flag} must be an absolute URL, got '${raw}'.`);
87
- }
88
- const local = u.hostname === 'localhost' || u.hostname === '127.0.0.1' || u.hostname.endsWith('.localhost');
89
- if (u.protocol !== 'https:' && !(u.protocol === 'http:' && local)) {
90
- throw new errors_1.CliError(`${flag} must use https (http only for localhost), got '${raw}'.`);
91
- }
92
- return raw.replace(/\/+$/, '');
93
- }
94
- /** Platform clock minus ours, in ms, from a ping. */
95
- function pingSkewMs(ping, receivedAt, latencyMs) {
96
- if (typeof ping.clock_skew_ms === 'number')
97
- return ping.clock_skew_ms;
98
- if (ping.server_time === undefined || ping.server_time === null)
99
- return null;
100
- const server = typeof ping.server_time === 'number' ? ping.server_time : Date.parse(ping.server_time);
101
- if (!Number.isFinite(server))
102
- return null;
103
- return Math.round(server - (receivedAt - (latencyMs ?? 0) / 2));
104
- }
105
- /** Lines describing a connection test (a ping where the provider supports it). */
106
- function describeTestLines(test, receivedAt) {
107
- const lines = [];
108
- const meta = [test.http_status ? `HTTP ${test.http_status}` : '', typeof test.latency_ms === 'number' ? `${Math.round(test.latency_ms)} ms` : '']
109
- .filter(Boolean)
110
- .join(', ');
111
- lines.push(test.ok ? `Connection OK${meta ? ` (${meta})` : ''}.` : `Connection test failed${meta ? ` (${meta})` : ''}: ${test.error?.message ?? 'no answer'}.`);
112
- const ping = test.ping;
113
- if (ping) {
114
- if (ping.org_name)
115
- lines.push(` Organization: ${ping.org_name}`);
116
- const program = ping.program_name && ping.program_id ? `${ping.program_name} (${ping.program_id})` : (ping.program_name ?? ping.program_id);
117
- if (program)
118
- lines.push(` Program: ${program}`);
119
- if (typeof ping.auto_enroll_users === 'boolean')
120
- lines.push(` Auto-enroll users: ${ping.auto_enroll_users ? 'on' : 'off'}`);
121
- const skew = pingSkewMs(ping, receivedAt, test.latency_ms);
122
- if (skew !== null) {
123
- lines.push(` Clock skew: ${(skew / 1000).toFixed(1)} s`);
124
- if (Math.abs(skew) > 60_000) {
125
- lines.push(' Warning: the clocks differ by more than 60 seconds. Signed calls fail beyond 5 minutes.');
126
- }
127
- }
128
- }
129
- return lines;
130
- }
131
- /** A `customerRef,code` CSV → map; throws on a bad line. A header row is skipped. */
132
- function parseCodeCsv(text, flag = '--map') {
133
- const out = {};
134
- const lines = text.split(/\r?\n/);
135
- lines.forEach((line, i) => {
136
- const l = line.trim();
137
- if (!l || l.startsWith('#'))
138
- return;
139
- const [ref, code] = l.split(/[;,\t]/).map((x) => x.trim().replace(/^"(.*)"$/, '$1'));
140
- if (i === 0 && /^(customer_?ref|user_?id|external_?id|user)$/i.test(ref ?? ''))
141
- return;
142
- if (!ref || !code)
143
- throw new errors_1.CliError(`${flag} line ${i + 1}: expected customerRef,code.`);
144
- if (!/^[A-Za-z0-9_-]{3,64}$/.test(code))
145
- throw new errors_1.CliError(`${flag} line ${i + 1}: '${code}' is not a valid code.`);
146
- out[ref] = code;
147
- });
148
- return out;
149
- }
150
- /** One call to the Referalli merchant API with the merchant key. Throws a CliError naming `what` on failure. */
151
- async function referalliRequest(ctx, input) {
152
- const fetchImpl = ctx.fetch ?? globalThis.fetch;
153
- let res;
154
- try {
155
- res = await fetchImpl(`${input.baseUrl}${input.path}`, {
156
- method: input.method,
157
- headers: {
158
- authorization: `Bearer ${input.key}`,
159
- accept: 'application/json',
160
- 'referalli-version': exports.REFERALLI_VERSION,
161
- ...(input.body ? { 'content-type': 'application/json' } : {}),
162
- },
163
- ...(input.body ? { body: JSON.stringify(input.body) } : {}),
164
- });
165
- }
166
- catch (err) {
167
- throw new errors_1.CliError(`Could not reach Referalli at ${input.baseUrl}: ${err instanceof Error ? err.message : String(err)}`);
168
- }
169
- const text = await res.text();
170
- let json = {};
171
- try {
172
- json = text ? JSON.parse(text) : {};
173
- }
174
- catch {
175
- /* not JSON */
176
- }
177
- if (!res.ok) {
178
- const err = (json.error ?? json.errors);
179
- const msg = (typeof err === 'object' && err && 'message' in err ? String(err.message) : null) ??
180
- (Array.isArray(err) && err[0] && typeof err[0] === 'object' && 'message' in err[0] ? String(err[0].message) : null) ??
181
- (typeof json.message === 'string' ? json.message : null);
182
- const hint = res.status === 401 || res.status === 403 ? ' Check the merchant key.' : '';
183
- throw new errors_1.CliError(`Referalli refused to ${input.what} (HTTP ${res.status})${msg ? `: ${msg}` : ''}.${hint}`);
184
- }
185
- return json;
186
- }
187
- /** The exact origins of an instance's app: its allowed origins (no wildcards) and its Frontend API host. */
188
- function appOrigins(instance) {
189
- const out = new Set();
190
- const add = (raw) => {
191
- if (typeof raw !== 'string' || raw.includes('*'))
192
- return;
193
- try {
194
- const u = new URL(raw);
195
- if (u.protocol === 'https:' || u.protocol === 'http:')
196
- out.add(u.origin);
197
- }
198
- catch {
199
- /* not a URL */
200
- }
201
- };
202
- for (const o of instance.allowed_origins ?? [])
203
- add(typeof o === 'object' && o !== null ? o.origin : o);
204
- if (instance.frontend_api_host)
205
- add(`https://${instance.frontend_api_host}`);
206
- return [...out].sort();
207
- }
208
- async function referalliCreateConnection(ctx, input) {
209
- const json = await referalliRequest(ctx, { ...input, method: 'POST', path: '/v1/auth/connections', what: 'create the connection' });
210
- if (typeof json.id !== 'string' || typeof json.secret !== 'string') {
211
- throw new errors_1.CliError('Referalli answered without a connection id and secret.');
212
- }
213
- return json;
214
- }
215
- /** The Referalli topics two-way sync subscribes to (changes to a referral after sign-up). */
216
- exports.REFERALLI_SYNC_TOPICS = [
217
- 'referral.created',
218
- 'referral.held',
219
- 'referral.paused',
220
- 'referral.resumed',
221
- 'referral.approved',
222
- 'referral.voided',
223
- 'referral.reassigned',
224
- ];
225
- /**
226
- * Whether the merchant key reaches live or test data: the org's `livemode`,
227
- * else the key prefix (rk_test_ = test; rk_live_ and older rk_ keys = live).
228
- * `known` is false when Referalli reports no mode (no test mode there).
229
- */
230
- async function referalliKeyMode(ctx, input) {
231
- const org = await referalliTry(ctx, { ...input, path: '/v1/org', what: 'read the organization' });
232
- if (typeof org?.livemode === 'boolean')
233
- return { live: org.livemode, known: true, org };
234
- if (input.key.startsWith('rk_test_'))
235
- return { live: false, known: true, org };
236
- if (input.key.startsWith('rk_live_'))
237
- return { live: true, known: true, org };
238
- return { live: true, known: false, org };
239
- }
240
- /** A best-effort Referalli read: null when it fails (an older Referalli, a key without access). */
241
- async function referalliTry(ctx, input) {
242
- try {
243
- return await referalliRequest(ctx, { ...input, method: 'GET' });
244
- }
245
- catch (err) {
246
- if (err instanceof errors_1.CliError)
247
- return null;
248
- throw err;
249
- }
250
- }
251
- /** A Referalli list answer: a plain array (API version 2026-10-21) or a `{ data: [...] }` page. */
252
- function referalliList(body) {
253
- const rows = Array.isArray(body) ? body : body && typeof body === 'object' && Array.isArray(body.data) ? body.data : [];
254
- return rows.filter((r) => !!r && typeof r === 'object' && !Array.isArray(r));
255
- }
256
- /** Referalli's public tracked link for a code: `{host}/go/{trackingToken}/{code}`, on the org's link domain once it is active. */
257
- function referalliLinkTemplate(baseUrl, trackingToken, branding) {
258
- const domain = branding?.linkDomainStatus === 'active' && typeof branding.linkDomain === 'string' && branding.linkDomain ? branding.linkDomain : null;
259
- return `${domain ? `https://${domain}` : baseUrl}/go/${encodeURIComponent(trackingToken)}/{code}`;
260
- }
261
- /** The merchant key from --referalli-key / --referalli-key-file / REFERALLI_API_KEY (or their old names); never printed. */
262
- function referalliKeyFrom(ctx, v) {
263
- const oldKeyFile = (0, args_1.str)(v, LEGACY.keyFileFlag);
264
- const oldKey = (0, args_1.str)(v, LEGACY.keyFlag);
265
- if (oldKeyFile)
266
- legacyNotice(ctx, `--${LEGACY.keyFileFlag}`, '--referalli-key-file');
267
- if (oldKey)
268
- legacyNotice(ctx, `--${LEGACY.keyFlag}`, '--referalli-key');
269
- const legacyKey = ctx.env[LEGACY.apiKeyEnv]?.trim();
270
- legacyEnvNotice(ctx);
271
- const keyFile = (0, args_1.str)(v, 'referalli-key-file') ?? oldKeyFile;
272
- return ((0, args_1.str)(v, 'referalli-key') ??
273
- oldKey ??
274
- (keyFile ? readKeyFile(ctx, keyFile, 'the Referalli key') : (ctx.env.REFERALLI_API_KEY?.trim() || legacyKey || undefined)));
275
- }
276
- /** The `programIds` a Referalli webhook endpoint is limited to: null or [] means every program in the organization. */
277
- function webhookScope(endpoint) {
278
- if (!endpoint)
279
- return { scope: 'unknown', program_ids: null };
280
- const ids = Array.isArray(endpoint.programIds) ? endpoint.programIds.filter((x) => typeof x === 'string') : [];
281
- return ids.length ? { scope: 'program', program_ids: ids } : { scope: 'all_programs', program_ids: null };
282
- }
283
- /**
284
- * The two-way sync webhook on Referalli, limited to the connected program
285
- * (`programIds: [program]`) so another product's referrals in a shared
286
- * organization never reach this instance. Idempotent: an endpoint already
287
- * pointing at this instance's inbound URL is reused and re-scoped in place
288
- * (an unscoped one from an earlier run is repaired); its secret is rotated
289
- * only when Atlas does not hold it (`held`: the endpoint whose secret Atlas
290
- * stores). `secret` is null when nothing new needs saving.
291
- */
292
- async function referalliSyncEndpoint(ctx, input) {
293
- const { baseUrl, key } = input;
294
- const scope = { topics: [...exports.REFERALLI_SYNC_TOPICS], legacySignature: false, programIds: [input.program] };
295
- const listed = await referalliTry(ctx, { baseUrl, key, path: '/v1/webhook-endpoints', what: 'list the webhook endpoints' });
296
- const mine = referalliList(listed).filter((e) => e.url === input.url && typeof e.id === 'string');
297
- const found = mine.find((e) => e.id === input.held) ?? mine[0];
298
- if (!found) {
299
- const endpoint = await referalliRequest(ctx, {
300
- baseUrl,
301
- key,
302
- method: 'POST',
303
- path: '/v1/webhook-endpoints',
304
- body: { url: input.url, ...scope },
305
- what: 'register the referral event webhook',
306
- });
307
- if (typeof endpoint.id !== 'string' || typeof endpoint.secret !== 'string') {
308
- throw new errors_1.CliError('Referalli answered without a webhook endpoint id and secret.');
309
- }
310
- return { id: endpoint.id, secret: endpoint.secret, duplicates: [] };
311
- }
312
- const id = found.id;
313
- const duplicates = mine.filter((e) => e !== found).map((e) => e.id);
314
- await referalliRequest(ctx, {
315
- baseUrl,
316
- key,
317
- method: 'PATCH',
318
- path: `/v1/webhook-endpoints/${encodeURIComponent(id)}`,
319
- body: scope,
320
- what: 'limit the referral event webhook to the program',
321
- });
322
- if (id === input.held)
323
- return { id, secret: null, duplicates };
324
- const rotated = await referalliRequest(ctx, {
325
- baseUrl,
326
- key,
327
- method: 'POST',
328
- path: `/v1/webhook-endpoints/${encodeURIComponent(id)}/rotate-secret`,
329
- body: {},
330
- what: 'rotate the referral event webhook secret',
331
- });
332
- if (typeof rotated.secret !== 'string')
333
- throw new errors_1.CliError('Referalli answered without a webhook secret.');
334
- return { id, secret: rotated.secret, duplicates };
335
- }
336
- /**
337
- * `connect --provider referalli --oauth`: Atlas starts an OAuth install at
338
- * Referalli. The merchant opens the printed link, picks an organization and
339
- * program, and Referalli returns the connection secret to Atlas directly. The
340
- * command waits until the instance shows the new connection, then pings it.
341
- */
342
- async function connectWithOAuth(ctx, args, io) {
343
- const v = args.values;
344
- const { http, json, out, presetId } = io;
345
- const before = await http.get('/v1/instance/referrals');
346
- let started;
347
- try {
348
- started = await http.post(`/v1/instance/referrals/${encodeURIComponent(presetId)}/install`, {});
349
- }
350
- catch (err) {
351
- if (err instanceof backend_1.AtlasApiError && err.status === 422) {
352
- throw new errors_1.CliError(`One-click connect to '${presetId}' is not available on this Atlas. Connect with a key or the signing secret instead (atlas referrals connect --provider referalli --program <prg_…> --base-url <url> --referalli-key-file <path>, or --provider webhook --endpoint <url>).`);
353
- }
354
- throw err;
355
- }
356
- if (json)
357
- ctx.io.err(`atlas: open ${started.authorize_url}`);
358
- else {
359
- out.out('Open this link, choose your Referalli organization and program, and approve:');
360
- out.out('');
361
- out.out(` ${started.authorize_url}`);
362
- out.out('');
363
- out.out('Waiting for Referalli to finish (the link is valid for 15 minutes)…');
364
- }
365
- const sleep = ctx.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
366
- const now = () => Date.now();
367
- let after = before;
368
- const changed = (s) => s.signing_secret_set && (s.provider !== before.provider || s.connection_id !== before.connection_id || s.endpoint_url !== before.endpoint_url || s.updated_at !== before.updated_at);
369
- while (!changed(after)) {
370
- if (now() > started.expires_at)
371
- throw new errors_1.CliError('The link expired before Referalli finished. Run the command again.');
372
- await sleep(2000);
373
- after = await http.get('/v1/instance/referrals');
374
- }
375
- const test = await http.post('/v1/instance/referrals/test', {});
376
- const receivedAt = Date.now();
377
- let enabled = false;
378
- if (v.enable === true) {
379
- if (!test.ok)
380
- ctx.io.err('atlas: not turning referrals on: the connection test failed.');
381
- else {
382
- await http.patch('/v1/instance/referrals', { enabled: true, ...(v['no-identity-backfill'] === true ? { backfill_existing_users: false } : {}) });
383
- enabled = true;
384
- }
385
- }
386
- if (json) {
387
- (0, output_1.printJson)(ctx.io, { provider: after.provider, preset: presetId, connection_id: after.connection_id, program_id: after.program_id, test, enabled });
388
- }
389
- else {
390
- out.out(`Connected to ${presetId} (${after.connection_id ? `connection ${after.connection_id}` : (after.endpoint_url ?? 'endpoint set')}${after.program_id ? `, program ${after.program_id}` : ''}). No secret was shown or copied.`);
391
- for (const line of describeTestLines(test, receivedAt))
392
- ctx.io.out(line);
393
- ctx.io.out(enabled
394
- ? 'Referral attribution is on.'
395
- : v.enable === true
396
- ? 'Referral attribution stays off until the test passes.'
397
- : "Turn it on with 'atlas referrals connect --provider referalli --oauth --enable', or in the dashboard (Users → Referrals).");
398
- }
399
- return test.ok ? 0 : 1;
400
- }
401
- /**
402
- * `connect --dry-run`: list the platform calls it would make, and validate the
403
- * Atlas settings write with `?dry_run=true` (nothing is saved, no secret kept).
404
- */
405
- async function printDryRun(ctx, json, planned, atlas) {
406
- const result = atlas
407
- ? await atlas.http.patch('/v1/instance/referrals?dry_run=true', atlas.patch)
408
- : null;
409
- const redacted = atlas ? { ...atlas.patch, ...('signing_secret' in atlas.patch ? { signing_secret: '<redacted>' } : {}) } : null;
410
- if (json) {
411
- (0, output_1.printJson)(ctx.io, { dry_run: true, planned_requests: planned, atlas_request: redacted && { method: 'PATCH', path: '/v1/instance/referrals', body: redacted }, atlas_result: result });
412
- }
413
- else {
414
- for (const p of planned)
415
- ctx.io.out(`Would call: ${p}`);
416
- if (redacted) {
417
- ctx.io.out(`Would save: PATCH /v1/instance/referrals ${JSON.stringify(redacted)}`);
418
- ctx.io.out(result?.validated === false ? 'Atlas could not fully validate it in a dry run.' : 'Atlas validated the settings.');
419
- }
420
- ctx.io.out('Dry run: nothing was written and no connection test was run.');
421
- }
422
- return 0;
423
- }
424
- async function connect(ctx, args) {
425
- const v = args.values;
426
- const json = (0, shared_1.wantsJson)(v);
427
- let provider = (0, args_1.str)(v, 'provider') ?? 'referalli';
428
- if (provider === LEGACY.provider) {
429
- legacyNotice(ctx, '--provider referally', '--provider referalli');
430
- provider = 'referalli';
431
- }
432
- if (!PROVIDERS.includes(provider)) {
433
- throw new errors_1.CliError(`--provider must be one of ${PROVIDERS.join(', ')}, got '${provider}'.`);
434
- }
435
- const cred = (0, project_commands_1.instanceCredential)(ctx, args);
436
- const http = (0, project_1.httpFor)(ctx, cred);
437
- // --dry-run: reads only. Atlas validates the settings write with ?dry_run=true; calls to the platform are listed, not made.
438
- const dryRun = v['dry-run'] === true;
439
- // One-click: the platform asks the merchant for the organization and program and hands Atlas the secret.
440
- // Any platform the deployment offers works (--preset <id>); Referalli is the default preset.
441
- if (v.oauth === true) {
442
- const presetId = (0, args_1.str)(v, 'preset') ?? (provider === 'webhook' ? null : 'referalli');
443
- if (!presetId)
444
- throw new errors_1.CliError('referrals connect --provider webhook --oauth needs --preset <id> (see one_click_presets in `atlas referrals status --json`).');
445
- if (dryRun)
446
- return printDryRun(ctx, json, [`POST /v1/instance/referrals/${presetId}/install (then you approve on the platform)`], null);
447
- return connectWithOAuth(ctx, args, { http, json, out: json ? { out: () => undefined } : ctx.io, presetId });
448
- }
449
- const product = (0, args_1.str)(v, 'product') ?? 'atlasauth';
450
- const out = json ? { out: () => undefined, err: ctx.io.err } : ctx.io;
451
- let patch;
452
- let summary;
453
- if (provider === 'referalli') {
454
- const program = (0, args_1.str)(v, 'program');
455
- if (!program)
456
- throw new errors_1.CliError('referrals connect --provider referalli needs --program <prg_…>.');
457
- const legacyBase = ctx.env[LEGACY.baseUrlEnv]?.trim();
458
- legacyEnvNotice(ctx);
459
- const baseRaw = (0, args_1.str)(v, 'base-url') ?? ctx.env.REFERALLI_BASE_URL?.trim() ?? legacyBase;
460
- if (!baseRaw)
461
- throw new errors_1.CliError('Pass --base-url <your Referalli base URL> (or set REFERALLI_BASE_URL).');
462
- const baseUrl = httpsUrl(baseRaw, '--base-url');
463
- const key = referalliKeyFrom(ctx, v);
464
- if (!key) {
465
- throw new errors_1.CliError('Pass your Referalli merchant key with --referalli-key-file <path|-> (or --referalli-key, or REFERALLI_API_KEY). It is used once and never stored.');
466
- }
467
- const destination = (0, args_1.str)(v, 'destination');
468
- if (destination)
469
- httpsUrl(destination, '--destination');
470
- const instance = await http.get('/v1/instance');
471
- // Test data for development instances, live data for production: a mix-up
472
- // would pay real partners for test sign-ups, or lose real ones.
473
- const instanceLive = instance.environment === 'production';
474
- const mode = await referalliKeyMode(ctx, { baseUrl, key });
475
- if (mode.known && mode.live !== instanceLive) {
476
- const message = `the Referalli key reaches ${mode.live ? 'live' : 'test'} data but instance ${instance.id} is ` +
477
- `${instance.environment ?? 'not production'}. Use ${instanceLive ? 'a live (rk_live_…)' : 'a test (rk_test_…)'} key` +
478
- ` for it, or pass --allow-mode-mismatch.`;
479
- if (v['allow-mode-mismatch'] !== true)
480
- throw new errors_1.CliError(message.charAt(0).toUpperCase() + message.slice(1));
481
- ctx.io.err(`atlas: warning: ${message.replace(/, or pass --allow-mode-mismatch\.$/, '.')}`);
482
- }
483
- else if (!mode.known && !instanceLive) {
484
- ctx.io.err(`atlas: warning: Referalli did not say whether this key reaches test data; instance ${instance.id} is ${instance.environment ?? 'not production'}.`);
485
- }
486
- // The app's origins travel with the connection (Referalli's widget CORS then needs no dashboard step); kept current by Atlas afterwards.
487
- const origins = appOrigins(instance);
488
- const enrollment = {
489
- ...(v['auto-enroll'] === true ? { autoEnrollUsers: true } : {}),
490
- ...(origins.length ? { allowedOrigins: origins } : {}),
491
- ...(destination ? { destinationUrl: destination } : {}),
492
- };
493
- const current = await http.get('/v1/instance/referrals');
494
- // Re-runs reuse the instance's connection, updated in place: Referalli keeps one per instance per organization.
495
- const listed = await referalliTry(ctx, { baseUrl, key, path: '/v1/auth/connections', what: 'list the connections' });
496
- const existing = referalliList(listed).find((c) => c.provider === 'atlas' && c.instanceId === instance.id && typeof c.id === 'string');
497
- if (existing && typeof existing.programId === 'string' && existing.programId !== program) {
498
- throw new errors_1.CliError(`Referalli already has connection ${String(existing.id)} for instance ${instance.id}, in program ${existing.programId}. ` +
499
- `It allows one per instance: run again with --program ${existing.programId}, or delete that connection on Referalli first.`);
500
- }
501
- if (dryRun) {
502
- const held = existing && current.connection_id === existing.id && current.signing_secret_set;
503
- const planned = existing
504
- ? [
505
- ...(held ? [] : [`POST ${baseUrl}/v1/auth/connections/${String(existing.id)}/rotate-secret`]),
506
- `PATCH ${baseUrl}/v1/auth/connections/${String(existing.id)} ${JSON.stringify({ signatureVersion: 'v2', ...enrollment })}`,
507
- ]
508
- : [
509
- `POST ${baseUrl}/v1/auth/connections ${JSON.stringify({ provider: 'atlas', instanceId: instance.id, programId: program, ...enrollment })}`,
510
- `PATCH ${baseUrl}/v1/auth/connections/<new id> {"signatureVersion":"v2"}`,
511
- ];
512
- if (v['no-sync'] !== true)
513
- planned.push(`Register the two-way sync webhook on Referalli for program ${program}`);
514
- const tracking = (0, args_1.str)(v, 'tracking-token') ?? (typeof mode.org?.trackingToken === 'string' ? mode.org.trackingToken : null);
515
- const linkTemplate = (0, args_1.str)(v, 'link-template');
516
- return printDryRun(ctx, json, planned, {
517
- http,
518
- patch: {
519
- provider: 'referalli',
520
- endpoint_url: baseUrl,
521
- ...(existing ? { connection_id: existing.id } : {}),
522
- program_id: program,
523
- ...(v['auto-enroll'] === true ? { auto_enroll_users: true } : {}),
524
- ...(tracking ? { tracking_token: tracking } : {}),
525
- ...(linkTemplate ? { link_template: linkTemplate } : {}),
526
- },
527
- });
528
- }
529
- let connectionId;
530
- // Null when Atlas already holds the reused connection's secret.
531
- let secret = null;
532
- let createdToken = null;
533
- if (existing) {
534
- connectionId = existing.id;
535
- if (current.connection_id !== connectionId || !current.signing_secret_set) {
536
- // Atlas does not hold this connection's secret: rotate it (the old one keeps verifying for 24 hours).
537
- const rotated = await referalliRequest(ctx, {
538
- baseUrl,
539
- key,
540
- method: 'POST',
541
- path: `/v1/auth/connections/${encodeURIComponent(connectionId)}/rotate-secret`,
542
- body: {},
543
- what: 'rotate the connection secret',
544
- });
545
- if (typeof rotated.secret !== 'string')
546
- throw new errors_1.CliError('Referalli answered without a connection secret.');
547
- secret = rotated.secret;
548
- }
549
- }
550
- else {
551
- const created = await referalliCreateConnection(ctx, {
552
- baseUrl,
553
- key,
554
- body: { provider: 'atlas', instanceId: instance.id, programId: program, ...enrollment },
555
- });
556
- connectionId = created.id;
557
- secret = created.secret;
558
- createdToken = typeof created.trackingToken === 'string' ? created.trackingToken : null;
559
- }
560
- // Atlas always signs with v2: require it from the first call, so v1 is never accepted on this connection.
561
- let signatureV2 = true;
562
- try {
563
- await referalliRequest(ctx, {
564
- baseUrl,
565
- key,
566
- method: 'PATCH',
567
- path: `/v1/auth/connections/${encodeURIComponent(connectionId)}`,
568
- body: { signatureVersion: 'v2', ...(existing ? enrollment : {}) },
569
- what: existing ? 'update the connection' : 'require v2 signatures on the connection',
570
- });
571
- }
572
- catch (err) {
573
- signatureV2 = false;
574
- ctx.io.err(`atlas: warning: ${err instanceof Error ? err.message : String(err)} It switches to v2 on Atlas's first call anyway.`);
575
- }
576
- // The org's public tracking token (GET /v1/org) builds Referalli's tracked links; a link template set before is kept.
577
- const orgToken = typeof mode.org?.trackingToken === 'string' ? mode.org.trackingToken : null;
578
- const trackingToken = (0, args_1.str)(v, 'tracking-token') ?? orgToken ?? createdToken;
579
- let linkTemplate = (0, args_1.str)(v, 'link-template') ?? null;
580
- if (!linkTemplate && !current.link_template && trackingToken) {
581
- const branding = await referalliTry(ctx, { baseUrl, key, path: '/v1/branding', what: 'read the link domain' });
582
- linkTemplate = referalliLinkTemplate(baseUrl, trackingToken, branding);
583
- }
584
- patch = {
585
- provider: 'referalli',
586
- endpoint_url: baseUrl,
587
- connection_id: connectionId,
588
- ...(secret ? { signing_secret: secret } : {}),
589
- program_id: program,
590
- ...(v['auto-enroll'] === true ? { auto_enroll_users: true } : {}),
591
- ...(trackingToken ? { tracking_token: trackingToken } : {}),
592
- ...(linkTemplate ? { link_template: linkTemplate } : {}),
593
- };
594
- let saved;
595
- try {
596
- saved = await http.patch('/v1/instance/referrals', patch);
597
- }
598
- catch (err) {
599
- // The secret is shown once by Referalli: keep it so the merchant can finish by hand.
600
- const kept = secret
601
- ? (0, secrets_1.deliverSecret)({
602
- io: out,
603
- env: ctx.env,
604
- product,
605
- fileName: `referalli-connection-${connectionId}.env`,
606
- entries: { REFERALLI_CONNECTION_ID: connectionId, REFERALLI_CONNECTION_SECRET: secret },
607
- label: 'The Referalli connection secret (not saved on Atlas)',
608
- force: v.force === true,
609
- comment: `Referalli connection ${connectionId}: saving it on the Atlas instance failed. Paste it in Users → Referrals.`,
610
- })
611
- : { path: undefined };
612
- ctx.io.err(`atlas: the connection ${connectionId} ${existing ? 'exists' : 'was created'} on Referalli, but saving it on the instance failed.${kept.path ? ` Its secret is in ${kept.path}.` : ''}`);
613
- throw err;
614
- }
615
- // Two-way sync: Referalli's referral events for this program go to the instance's inbound URL.
616
- let syncEndpoint = null;
617
- let syncScope = null;
618
- const inboundUrl = saved?.inbound?.url ?? null;
619
- if (v['no-sync'] !== true && inboundUrl) {
620
- try {
621
- const sync = await referalliSyncEndpoint(ctx, {
622
- baseUrl,
623
- key,
624
- url: inboundUrl,
625
- program,
626
- held: current.inbound?.secret_set ? (current.inbound.endpoint_id ?? null) : null,
627
- });
628
- if (!sync.secret) {
629
- syncEndpoint = sync.id;
630
- syncScope = [program];
631
- }
632
- else {
633
- try {
634
- await http.patch('/v1/instance/referrals', { inbound_secret: sync.secret, inbound_endpoint_id: sync.id });
635
- syncEndpoint = sync.id;
636
- syncScope = [program];
637
- }
638
- catch (err) {
639
- const kept = (0, secrets_1.deliverSecret)({
640
- io: out,
641
- env: ctx.env,
642
- product,
643
- fileName: `referalli-webhook-${sync.id}.env`,
644
- entries: { REFERALLI_WEBHOOK_ENDPOINT_ID: sync.id, REFERALLI_WEBHOOK_SECRET: sync.secret },
645
- label: 'The Referalli webhook secret (not saved on Atlas)',
646
- force: v.force === true,
647
- comment: `Referalli webhook ${sync.id}: saving it on the Atlas instance failed. Paste it as the inbound secret in Users → Referrals.`,
648
- });
649
- ctx.io.err(`atlas: warning: the webhook ${sync.id} was registered on Referalli, but saving its secret failed (${err instanceof Error ? err.message : String(err)}).${kept.path ? ` It is in ${kept.path}.` : ''}`);
650
- }
651
- }
652
- if (sync.duplicates.length) {
653
- ctx.io.err(`atlas: warning: Referalli has more webhook endpoints for this instance (${sync.duplicates.join(', ')}). Atlas cannot verify their deliveries; delete them on Referalli.`);
654
- }
655
- }
656
- catch (err) {
657
- if (!(err instanceof errors_1.CliError))
658
- throw err;
659
- ctx.io.err(`atlas: warning: ${err.message} Referral changes on Referalli won't reach Atlas until it is registered (see the docs).`);
660
- }
661
- }
662
- // What connect could not set: the exact settings call that finishes it.
663
- const leftToDo = {};
664
- if (!(trackingToken ?? current.tracking_token))
665
- leftToDo.tracking_token = '<your Referalli tracking token (tk_…), from GET /v1/org on Referalli>';
666
- if (!(linkTemplate ?? current.link_template))
667
- leftToDo.link_template = 'https://<your Referalli link host>/go/<tracking token>/{code}';
668
- summary = {
669
- provider: 'referalli',
670
- instance_id: instance.id,
671
- endpoint_url: baseUrl,
672
- connection_id: connectionId,
673
- reused: Boolean(existing),
674
- program_id: program,
675
- tracking_token: trackingToken ?? current.tracking_token ?? null,
676
- link_template: linkTemplate ?? current.link_template ?? null,
677
- livemode: mode.known ? mode.live : null,
678
- signature_v2_required: signatureV2,
679
- sync_endpoint_id: syncEndpoint,
680
- sync_program_ids: syncScope,
681
- left_to_do: Object.keys(leftToDo).length ? { method: 'PATCH', path: '/v1/instance/referrals', body: leftToDo } : null,
682
- };
683
- if (!json) {
684
- out.out(existing
685
- ? `Reused Referalli connection ${connectionId} for instance ${instance.id} and updated it${secret ? ' (new secret saved, not printed)' : ''}.`
686
- : `Created Referalli connection ${connectionId} for instance ${instance.id} and saved it (the secret was not printed).`);
687
- if (syncEndpoint)
688
- out.out(`Referral changes on Referalli sync back to Atlas (webhook ${syncEndpoint}, program ${program} only).`);
689
- if (Object.keys(leftToDo).length) {
690
- out.out(`Left to do: ${Object.keys(leftToDo).join(' and ')} could not be read from Referalli. Set them with PATCH /v1/instance/referrals:`);
691
- out.out(` ${JSON.stringify(leftToDo)}`);
692
- out.out(' (or run this again with --tracking-token <tk_…> and --link-template <url with {code}>)');
693
- }
694
- }
695
- }
696
- else {
697
- const endpoint = (0, args_1.str)(v, 'endpoint');
698
- if (!endpoint)
699
- throw new errors_1.CliError('referrals connect --provider webhook needs --endpoint <https-url>.');
700
- const endpointUrl = httpsUrl(endpoint, '--endpoint');
701
- const secretFile = (0, args_1.str)(v, 'secret-file');
702
- let secret;
703
- let generated = false;
704
- if (secretFile)
705
- secret = readKeyFile(ctx, secretFile, 'the signing secret');
706
- else {
707
- secret = `rfs_${(0, node_crypto_1.randomBytes)(32).toString('base64url')}`;
708
- generated = true;
709
- }
710
- if (secret.length < 16)
711
- throw new errors_1.CliError('The signing secret must be at least 16 characters.');
712
- patch = {
713
- provider: 'webhook',
714
- endpoint_url: endpointUrl,
715
- signing_secret: secret,
716
- ...((0, args_1.str)(v, 'program') ? { program_id: (0, args_1.str)(v, 'program') } : {}),
717
- ...(v['auto-enroll'] === true ? { auto_enroll_users: true } : {}),
718
- };
719
- // A generated secret is only validated here, never saved or printed.
720
- if (dryRun)
721
- return printDryRun(ctx, json, [], { http, patch });
722
- await http.patch('/v1/instance/referrals', patch);
723
- let secretPath;
724
- if (generated) {
725
- secretPath = (0, secrets_1.deliverSecret)({
726
- io: out,
727
- env: ctx.env,
728
- product,
729
- fileName: 'referrals-signing-secret.env',
730
- entries: { ATLAS_REFERRALS_SIGNING_SECRET: secret },
731
- label: 'The signing secret (configure it on your referral platform)',
732
- printSecret: v['print-secret'] === true,
733
- force: v.force === true,
734
- comment: `Signing secret for Atlas referral calls to ${endpointUrl}.`,
735
- }).path;
736
- }
737
- const inboundUrl = (await http.get('/v1/instance/referrals')).inbound?.url ?? null;
738
- summary = { provider: 'webhook', endpoint_url: endpointUrl, secret_file: secretPath ?? null, inbound_url: inboundUrl };
739
- if (!json) {
740
- out.out(`Saved the referral protocol connection to ${endpointUrl}.`);
741
- if (inboundUrl)
742
- out.out(`For two-way sync, have the platform send referral changes to ${inboundUrl}, signed with the same secret.`);
743
- }
744
- }
745
- const test = await http.post('/v1/instance/referrals/test', {});
746
- const receivedAt = Date.now();
747
- let enabled = false;
748
- if (v.enable === true) {
749
- if (!test.ok) {
750
- ctx.io.err('atlas: not turning referrals on: the connection test failed.');
751
- }
752
- else {
753
- await http.patch('/v1/instance/referrals', { enabled: true, ...(v['no-identity-backfill'] === true ? { backfill_existing_users: false } : {}) });
754
- enabled = true;
755
- }
756
- }
757
- if (json) {
758
- (0, output_1.printJson)(ctx.io, { ...summary, test, enabled });
759
- }
760
- else {
761
- for (const line of describeTestLines(test, receivedAt))
762
- ctx.io.out(line);
763
- ctx.io.out(enabled
764
- ? 'Referral attribution is on.'
765
- : v.enable === true
766
- ? 'Referral attribution stays off until the test passes.'
767
- : "Turn it on with 'atlas referrals connect … --enable', or in the dashboard (Users → Referrals).");
768
- }
769
- return test.ok ? 0 : 1;
770
- }
771
- async function backfill(ctx, args) {
772
- const v = args.values;
773
- const since = (0, args_1.str)(v, 'since');
774
- if (!since || !/^\d{4}-\d{2}-\d{2}(T.*)?$/.test(since) || Number.isNaN(Date.parse(since))) {
775
- throw new errors_1.CliError('referrals backfill needs --since <YYYY-MM-DD>.');
776
- }
777
- const readMap = (flag, file) => {
778
- if (!file)
779
- return undefined;
780
- let text;
781
- try {
782
- text = ctx.readFile(file === '-' ? '/dev/stdin' : file);
783
- }
784
- catch {
785
- throw new errors_1.CliError(`Could not read ${file}.`);
786
- }
787
- return parseCodeCsv(text, `--${flag}`);
788
- };
789
- const checkPath = (flag) => {
790
- const p = (0, args_1.str)(v, flag);
791
- if (p && !/^(public|private|unsafe)_metadata(\.[A-Za-z0-9_-]{1,64}){1,4}$/.test(p)) {
792
- throw new errors_1.CliError(`--${flag} must look like public_metadata.referral_code, got '${p}'.`);
793
- }
794
- return p;
795
- };
796
- const mapFile = (0, args_1.str)(v, 'map');
797
- const ownMapFile = (0, args_1.str)(v, 'own-map');
798
- if (mapFile === '-' && ownMapFile === '-')
799
- throw new errors_1.CliError('Only one of --map and --own-map can read stdin.');
800
- const codes = readMap('map', mapFile);
801
- const ownCodes = readMap('own-map', ownMapFile);
802
- const metadataPath = checkPath('metadata-path');
803
- const ownMetadataPath = checkPath('own-metadata-path');
804
- const http = (0, project_1.httpFor)(ctx, (0, project_commands_1.instanceCredential)(ctx, args));
805
- let job = await http.post('/v1/instance/referrals/backfill', {
806
- since,
807
- ...(codes && Object.keys(codes).length ? { codes } : {}),
808
- ...(metadataPath ? { code_metadata_path: metadataPath } : {}),
809
- ...(ownCodes && Object.keys(ownCodes).length ? { own_codes: ownCodes } : {}),
810
- ...(ownMetadataPath ? { own_code_metadata_path: ownMetadataPath } : {}),
811
- });
812
- const running = (s) => s === 'queued' || s === 'running' || s === 'pending';
813
- if (v.wait === true) {
814
- const sleep = ctx.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
815
- while (running(job.status)) {
816
- await sleep(2000);
817
- job = await http.get(`/v1/instance/referrals/backfill/${encodeURIComponent(job.id)}`);
818
- }
819
- }
820
- if ((0, shared_1.wantsJson)(v))
821
- (0, output_1.printJson)(ctx.io, job);
822
- else {
823
- const counts = [
824
- typeof job.users_scanned === 'number' ? `${job.users_scanned} users` : '',
825
- typeof job.calls_queued === 'number' ? `${job.calls_queued} calls queued` : '',
826
- typeof job.users_skipped === 'number' ? `${job.users_skipped} skipped` : '',
827
- job.calls ? `${job.calls.succeeded} sent, ${job.calls.failed} failed` : '',
828
- ].filter(Boolean);
829
- ctx.io.out(`Backfill ${job.id}: ${job.status}${counts.length ? ` (${counts.join(', ')})` : ''}.`);
830
- if (codes)
831
- ctx.io.out(`${Object.keys(codes).length} code(s) read from ${mapFile}.`);
832
- if (ownCodes)
833
- ctx.io.out(`${Object.keys(ownCodes).length} own code(s) read from ${ownMapFile}.`);
834
- if (typeof job.own_codes_set === 'number' && (ownCodes || ownMetadataPath))
835
- ctx.io.out(`${job.own_codes_set} own code(s) kept.`);
836
- if (job.own_codes_taken?.length) {
837
- ctx.io.err(`atlas: ${job.own_codes_taken.length} own code(s) already belong to another user, not set: ${job.own_codes_taken.join(', ')}`);
838
- }
839
- if (running(job.status) && v.wait !== true)
840
- ctx.io.out("Add --wait to follow it, or watch the delivery log in the dashboard.");
841
- if (job.truncated && job.next_since) {
842
- ctx.io.out(`Stopped at the cap. Run it again with --since ${new Date(job.next_since).toISOString().slice(0, 10)} for the rest.`);
843
- }
844
- if (job.error)
845
- ctx.io.err(`atlas: ${job.error}`);
846
- }
847
- return job.status === 'failed' || (job.calls?.failed ?? 0) > 0 ? 1 : 0;
848
- }
849
- async function resync(ctx, args) {
850
- const userId = args.positionals[2];
851
- if (!userId)
852
- throw new errors_1.CliError('referrals resync needs a user id: atlas referrals resync <user_id> [--dry-run].');
853
- const http = (0, project_1.httpFor)(ctx, (0, project_commands_1.instanceCredential)(ctx, args));
854
- const res = await http.post(`/v1/users/${encodeURIComponent(userId)}/referral/resync${args.values['dry-run'] === true ? '?dry_run=true' : ''}`, {});
855
- if ((0, shared_1.wantsJson)(args.values))
856
- (0, output_1.printJson)(ctx.io, res);
857
- else {
858
- ctx.io.out(`Re-reported ${res.user_id}: call ${res.call_id ?? '-'} ${res.call_status ?? 'not sent'}${args.values['dry-run'] === true ? ' (dry run, nothing sent)' : ''}.`);
859
- if (res.error)
860
- ctx.io.err(`atlas: ${res.error}`);
861
- const code = res.referral?.referral_code;
862
- if (code)
863
- ctx.io.out(`Referral code ${code}${res.referral?.referral_link ? `, link ${res.referral.referral_link}` : ''}.`);
864
- }
865
- return res.call_status === 'failed' ? 1 : 0;
866
- }
867
- const FINDING_COLUMNS = [
868
- { header: 'SEVERITY', get: (f) => f.severity },
869
- { header: 'CODE', get: (f) => f.code },
870
- { header: 'MESSAGE', get: (f) => f.message },
871
- ];
872
- async function status(ctx, args) {
873
- const http = (0, project_1.httpFor)(ctx, (0, project_commands_1.instanceCredential)(ctx, args));
874
- const settings = await http.get('/v1/instance/referrals');
875
- let findings = [];
876
- try {
877
- const report = await http.get('/v1/instance/preflight');
878
- findings = (report.findings ?? []).filter((f) => f.code.startsWith('referral'));
879
- }
880
- catch (err) {
881
- if (!(err instanceof backend_1.AtlasApiError))
882
- throw err;
883
- }
884
- // The sync webhook's program scope lives on Referalli: read it when a merchant key is given (never required).
885
- const inbound = settings.inbound;
886
- let webhook = null;
887
- const key = settings.provider === 'referalli' && settings.endpoint_url && inbound?.endpoint_id ? referalliKeyFrom(ctx, args.values) : undefined;
888
- if (key && settings.endpoint_url && inbound?.endpoint_id) {
889
- webhook = await referalliTry(ctx, {
890
- baseUrl: settings.endpoint_url,
891
- key,
892
- path: `/v1/webhook-endpoints/${encodeURIComponent(inbound.endpoint_id)}`,
893
- what: 'read the referral event webhook',
894
- });
895
- }
896
- const scope = webhookScope(webhook);
897
- if ((0, shared_1.wantsJson)(args.values)) {
898
- const c = settings.connection ?? null;
899
- (0, output_1.printJson)(ctx.io, {
900
- // Flat, stable fields for scripts; `settings` is the raw GET /v1/instance/referrals answer.
901
- status: {
902
- enabled: settings.enabled,
903
- provider: settings.provider,
904
- connection_id: settings.connection_id,
905
- program_id: settings.program_id,
906
- signing_secret_set: settings.signing_secret_set,
907
- webhook: {
908
- endpoint_id: inbound?.endpoint_id ?? null,
909
- url: inbound?.url ?? null,
910
- secret_set: inbound?.secret_set ?? false,
911
- // program: limited to program_ids; all_programs: every program in the organization; unknown: no merchant key given.
912
- scope: inbound?.endpoint_id ? scope.scope : null,
913
- program_ids: scope.program_ids,
914
- },
915
- link_template_set: Boolean(settings.link_template),
916
- tracking_token_set: Boolean(settings.tracking_token),
917
- last_sync: inbound?.last_event ?? null,
918
- last_test: c?.last_test ?? null,
919
- last_success_at: c?.last_success_at ?? null,
920
- missing: settings.missing ?? [],
921
- },
922
- settings,
923
- findings,
924
- });
925
- return findings.some((f) => f.severity === 'error') ? 1 : 0;
926
- }
927
- const c = settings.connection ?? null;
928
- const lines = [
929
- `Referral attribution: ${settings.enabled ? 'on' : 'off'}`,
930
- `Provider: ${settings.provider}`,
931
- `Endpoint: ${settings.endpoint_url ?? '(not set)'}`,
932
- `Connection ID: ${settings.connection_id ?? '(not set)'}`,
933
- `Program ID: ${settings.program_id ?? '(not set)'}`,
934
- `Signing secret: ${settings.signing_secret_set ? 'set' : 'not set'}`,
935
- `Link template: ${settings.link_template ?? '(not set)'}`,
936
- `Tracking token: ${settings.tracking_token ?? '(not set)'}`,
937
- ];
938
- if (settings.forward_lifecycle !== undefined)
939
- lines.push(`Forward lifecycle: ${settings.forward_lifecycle ? 'on' : 'off'}`);
940
- if (settings.missing?.length)
941
- lines.push(`Missing: ${settings.missing.join(', ')}`);
942
- if (c?.last_test) {
943
- lines.push(`Last test: ${c.last_test.ok ? 'ok' : `failed${c.last_test.error ? ` (${c.last_test.error})` : ''}`} at ${new Date(c.last_test.at).toISOString()}`);
944
- }
945
- if (c)
946
- lines.push(`Failed (7 days): ${c.failed_calls_7d ?? 0} Retrying: ${c.retrying_calls ?? 0}`);
947
- if (inbound?.url) {
948
- // Referalli needs its own webhook secret; the Atlas protocol falls back to the signing secret.
949
- const syncing = inbound.secret_set || (settings.provider === 'webhook' && settings.signing_secret_set);
950
- lines.push(`Two-way sync: ${syncing ? 'on' : 'off (no inbound secret)'}${inbound.endpoint_id ? ` (webhook ${inbound.endpoint_id})` : ''}`);
951
- if (scope.scope !== 'unknown') {
952
- lines.push(`Webhook scope: ${scope.program_ids ? `program ${scope.program_ids.join(', ')}` : 'every program (re-run connect to limit it)'}`);
953
- }
954
- lines.push(`Inbound URL: ${inbound.url}`);
955
- if (inbound.last_event) {
956
- lines.push(`Last event: ${inbound.last_event.type} → ${inbound.last_event.outcome} at ${new Date(inbound.last_event.at).toISOString()}`);
957
- }
958
- }
959
- for (const l of lines)
960
- ctx.io.out(l);
961
- if (c?.alert)
962
- ctx.io.out(`Alert: ${c.alert.code}${c.alert.message ? `: ${c.alert.message}` : ''}`);
963
- ctx.io.out('');
964
- if (findings.length === 0)
965
- ctx.io.out('No referral findings in preflight.');
966
- else {
967
- ctx.io.out((0, output_1.renderTable)(FINDING_COLUMNS, findings));
968
- for (const f of findings.filter((x) => x.severity !== 'info'))
969
- ctx.io.out(`${f.code}: ${f.fix}`);
970
- }
971
- return findings.some((f) => f.severity === 'error') ? 1 : 0;
972
- }
973
- /**
974
- * `atlas referrals conformance`: run the referral protocol conformance suite
975
- * (@atlasauth/referral-conformance) against a platform, and optionally Atlas's
976
- * own simulated sign-up against the connected instance.
977
- *
978
- * The platform defaults to the instance's configured Referalli endpoint and
979
- * connection id; the connection secret is never readable from Atlas, so it
980
- * comes from --secret-file (or '-' for stdin).
981
- */
982
- async function conformance(ctx, args) {
983
- const v = args.values;
984
- const json = (0, shared_1.wantsJson)(v);
985
- const http = (0, project_1.httpFor)(ctx, (0, project_commands_1.instanceCredential)(ctx, args));
986
- const settings = await http.get('/v1/instance/referrals');
987
- // Any platform: `webhook` tests the generic Atlas referral protocol, `connection` the connection-API dialect
988
- // (Referalli's). Default: what the instance is connected to.
989
- const profileFlag = (0, args_1.str)(v, 'protocol');
990
- if (profileFlag && profileFlag !== 'webhook' && profileFlag !== 'connection') {
991
- throw new errors_1.CliError(`--protocol must be webhook or connection, got '${profileFlag}'.`);
992
- }
993
- const profile = profileFlag ?? (settings.provider === 'webhook' ? 'webhook' : 'connection');
994
- const configured = settings.provider === 'webhook' || settings.provider === 'referalli';
995
- const baseRaw = (0, args_1.str)(v, 'base-url') ?? (configured ? settings.endpoint_url : null);
996
- if (!baseRaw)
997
- throw new errors_1.CliError('Pass --base-url <the platform to test> (or connect a platform first).');
998
- const baseUrl = httpsUrl(baseRaw, '--base-url');
999
- const connectionId = (0, args_1.str)(v, 'connection-id') ?? (profile === 'webhook' ? 'n/a' : settings.connection_id);
1000
- if (!connectionId)
1001
- throw new errors_1.CliError('Pass --connection-id <id> (the connection the suite signs its calls for).');
1002
- const secretFile = (0, args_1.str)(v, 'secret-file');
1003
- if (!secretFile) {
1004
- throw new errors_1.CliError('Pass --secret-file <path|-> with the connection secret. Atlas never shows it, so take it from the platform.');
1005
- }
1006
- const secret = readKeyFile(ctx, secretFile, 'the connection secret');
1007
- const only = (0, args_1.str)(v, 'only')
1008
- ?.split(',')
1009
- .map((s) => s.trim())
1010
- .filter(Boolean);
1011
- const report = await (0, referral_conformance_1.runConformance)({
1012
- profile,
1013
- baseUrl,
1014
- connectionId,
1015
- secret,
1016
- ...(ctx.fetch ? { fetch: ctx.fetch } : {}),
1017
- ...(only?.length ? { only } : {}),
1018
- });
1019
- let simulation = null;
1020
- if (v.simulate === true) {
1021
- simulation = await http.post('/v1/instance/referrals/simulate', {});
1022
- }
1023
- if (json)
1024
- (0, output_1.printJson)(ctx.io, { ...report, simulation });
1025
- else {
1026
- for (const line of (0, referral_conformance_1.formatReport)(report))
1027
- ctx.io.out(line);
1028
- if (simulation) {
1029
- ctx.io.out('');
1030
- ctx.io.out(simulation.ok === true
1031
- ? `Atlas's simulated sign-up reached the platform (call ${String(simulation.call_id ?? '')}).`
1032
- : `Atlas's simulated sign-up failed: ${String(simulation.error?.message ?? 'no answer')}.`);
1033
- }
1034
- }
1035
- return report.ok && (simulation === null || simulation.ok === true) ? 0 : 1;
1036
- }
1037
- async function referrals(ctx, args) {
1038
- const sub = args.positionals[1];
1039
- switch (sub) {
1040
- case 'connect':
1041
- return connect(ctx, args);
1042
- case 'backfill':
1043
- return backfill(ctx, args);
1044
- case 'resync':
1045
- return resync(ctx, args);
1046
- case 'status':
1047
- return status(ctx, args);
1048
- case 'conformance':
1049
- return conformance(ctx, args);
1050
- default:
1051
- throw new errors_1.CliError(sub
1052
- ? `Unknown subcommand 'referrals ${sub}'. Try: connect, backfill, resync, status, conformance.`
1053
- : 'referrals needs a subcommand: connect, backfill, resync, status, conformance.');
1054
- }
1055
- }
1056
- //# sourceMappingURL=referrals.js.map