@payloadcms/figma 0.0.1-alpha.8 → 0.1.0-alpha.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 (470) hide show
  1. package/dist/api/control-plane.d.ts +56 -7
  2. package/dist/api/control-plane.js +188 -74
  3. package/dist/api/error-response.d.ts +36 -0
  4. package/dist/api/error-response.js +66 -0
  5. package/dist/api/figma-api.d.ts +24 -3
  6. package/dist/api/figma-api.js +110 -34
  7. package/dist/auth/browser.d.ts +0 -1
  8. package/dist/auth/browser.js +0 -2
  9. package/dist/auth/callback-server.d.ts +19 -8
  10. package/dist/auth/callback-server.js +72 -32
  11. package/dist/auth/credentials.d.ts +20 -0
  12. package/dist/auth/credentials.js +19 -0
  13. package/dist/auth/crypto-utils.d.ts +28 -1
  14. package/dist/auth/crypto-utils.js +132 -23
  15. package/dist/auth/jwt-validator.d.ts +23 -6
  16. package/dist/auth/jwt-validator.js +35 -9
  17. package/dist/auth/oauth-flow.d.ts +19 -4
  18. package/dist/auth/oauth-flow.js +151 -34
  19. package/dist/auth/paste-code.d.ts +33 -0
  20. package/dist/auth/paste-code.js +87 -0
  21. package/dist/auth/pkce.d.ts +0 -1
  22. package/dist/auth/pkce.js +0 -2
  23. package/dist/auth/project-token.d.ts +32 -17
  24. package/dist/auth/project-token.js +176 -68
  25. package/dist/auth/refresh.d.ts +2 -2
  26. package/dist/auth/refresh.js +25 -14
  27. package/dist/auth/token-store-migration.d.ts +57 -0
  28. package/dist/auth/token-store-migration.js +154 -0
  29. package/dist/auth/token-store.d.ts +63 -98
  30. package/dist/auth/token-store.js +405 -124
  31. package/dist/auth/types.d.ts +40 -6
  32. package/dist/auth/types.js +1 -3
  33. package/dist/cli.d.ts +0 -1
  34. package/dist/cli.js +102 -8
  35. package/dist/commands/bootstrap.d.ts +17 -0
  36. package/dist/commands/bootstrap.js +88 -0
  37. package/dist/commands/build-lambda-zip.d.ts +4 -0
  38. package/dist/commands/build-lambda-zip.js +17 -0
  39. package/dist/commands/debug.d.ts +7 -0
  40. package/dist/commands/debug.js +178 -0
  41. package/dist/commands/deploy.d.ts +11 -1
  42. package/dist/commands/deploy.js +193 -153
  43. package/dist/commands/dump-tokens.d.ts +11 -0
  44. package/dist/commands/dump-tokens.js +67 -0
  45. package/dist/commands/env.d.ts +12 -0
  46. package/dist/commands/env.js +86 -0
  47. package/dist/commands/init.d.ts +9 -6
  48. package/dist/commands/init.js +232 -152
  49. package/dist/commands/list-tokens.d.ts +3 -4
  50. package/dist/commands/list-tokens.js +24 -11
  51. package/dist/commands/login.d.ts +8 -2
  52. package/dist/commands/login.js +34 -18
  53. package/dist/commands/logout.d.ts +5 -5
  54. package/dist/commands/logout.js +77 -17
  55. package/dist/commands/upgrade.d.ts +4 -0
  56. package/dist/commands/upgrade.js +329 -0
  57. package/dist/commands/upload-schema.d.ts +8 -0
  58. package/dist/commands/upload-schema.js +91 -0
  59. package/dist/config/oauth.d.ts +17 -12
  60. package/dist/config/oauth.js +38 -39
  61. package/dist/constants.d.ts +63 -19
  62. package/dist/constants.js +158 -20
  63. package/dist/db-content-api/generated/content-api-types.d.ts +7574 -0
  64. package/dist/db-content-api/generated/content-api-types.js +5 -0
  65. package/dist/db-content-api/index.d.ts +37 -0
  66. package/dist/db-content-api/index.js +938 -0
  67. package/dist/db-content-api/temp-utilities/slug.d.ts +1 -0
  68. package/dist/db-content-api/temp-utilities/slug.js +1 -0
  69. package/dist/db-content-api/temp-utilities/sorting.d.ts +2 -0
  70. package/dist/db-content-api/temp-utilities/sorting.js +37 -0
  71. package/dist/db-content-api/temp-utilities/types.d.ts +21 -0
  72. package/dist/db-content-api/temp-utilities/types.js +13 -0
  73. package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts +38 -0
  74. package/dist/db-content-api/temp-utilities/unwrapDocument.js +62 -0
  75. package/dist/db-content-api/utilities/auth.d.ts +29 -0
  76. package/dist/db-content-api/utilities/auth.js +82 -0
  77. package/dist/db-content-api/utilities/data/applyDefaults.d.ts +6 -0
  78. package/dist/db-content-api/utilities/data/applyDefaults.js +75 -0
  79. package/dist/db-content-api/utilities/data/castFieldValue.d.ts +10 -0
  80. package/dist/db-content-api/utilities/data/castFieldValue.js +66 -0
  81. package/dist/db-content-api/utilities/data/index.d.ts +48 -0
  82. package/dist/db-content-api/utilities/data/index.js +299 -0
  83. package/dist/db-content-api/utilities/data/pointShape.d.ts +3 -0
  84. package/dist/db-content-api/utilities/data/pointShape.js +43 -0
  85. package/dist/db-content-api/utilities/data/removeVirtualFields.d.ts +11 -0
  86. package/dist/db-content-api/utilities/data/removeVirtualFields.js +52 -0
  87. package/dist/db-content-api/utilities/data/richTextShape.d.ts +3 -0
  88. package/dist/db-content-api/utilities/data/richTextShape.js +56 -0
  89. package/dist/db-content-api/utilities/data/stripFields.d.ts +47 -0
  90. package/dist/db-content-api/utilities/data/stripFields.js +170 -0
  91. package/dist/db-content-api/utilities/data/transformPublishedLocale.d.ts +22 -0
  92. package/dist/db-content-api/utilities/data/transformPublishedLocale.js +40 -0
  93. package/dist/db-content-api/utilities/data/validateRelationships.d.ts +6 -0
  94. package/dist/db-content-api/utilities/data/validateRelationships.js +100 -0
  95. package/dist/db-content-api/utilities/joins.d.ts +52 -0
  96. package/dist/db-content-api/utilities/joins.js +137 -0
  97. package/dist/db-content-api/utilities/locale/index.d.ts +9 -0
  98. package/dist/db-content-api/utilities/locale/index.js +19 -0
  99. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.d.ts +10 -0
  100. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js +71 -0
  101. package/dist/db-content-api/utilities/meta/buildMeta.d.ts +41 -0
  102. package/dist/db-content-api/utilities/meta/buildMeta.js +39 -0
  103. package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts +16 -0
  104. package/dist/db-content-api/utilities/meta/buildPathTypes.js +243 -0
  105. package/dist/db-content-api/utilities/meta/buildUniquePaths.d.ts +12 -0
  106. package/dist/db-content-api/utilities/meta/buildUniquePaths.js +60 -0
  107. package/dist/db-content-api/utilities/meta/normalizeLocaleInWhere.d.ts +9 -0
  108. package/dist/db-content-api/utilities/meta/normalizeLocaleInWhere.js +100 -0
  109. package/dist/db-content-api/utilities/resolveBlocks.d.ts +19 -0
  110. package/dist/db-content-api/utilities/resolveBlocks.js +31 -0
  111. package/dist/db-content-api/utilities/schema/buildDocumentSchema.d.ts +55 -0
  112. package/dist/db-content-api/utilities/schema/buildDocumentSchema.js +182 -0
  113. package/dist/db-content-api/utilities/where.d.ts +19 -0
  114. package/dist/db-content-api/utilities/where.js +106 -0
  115. package/dist/deploy/schedule-extract-plugin.d.ts +10 -0
  116. package/dist/deploy/schedule-extract-plugin.js +32 -0
  117. package/dist/endpoints/health.d.ts +2 -0
  118. package/dist/endpoints/health.js +9 -0
  119. package/dist/endpoints/schema.d.ts +2 -0
  120. package/dist/endpoints/schema.js +27 -0
  121. package/dist/exports/client.d.ts +2 -1
  122. package/dist/exports/client.js +2 -2
  123. package/dist/index.d.ts +2 -2
  124. package/dist/index.js +3 -3
  125. package/dist/lib/download-skill.d.ts +12 -0
  126. package/dist/lib/download-skill.js +77 -0
  127. package/dist/oauth/components/FigmaAvatar/index.d.ts +3 -0
  128. package/dist/oauth/components/FigmaAvatar/index.js +25 -0
  129. package/dist/oauth/components/FigmaAvatar/index.scss +12 -0
  130. package/dist/oauth/components/FigmaAvatarCell/index.d.ts +4 -0
  131. package/dist/oauth/components/FigmaAvatarCell/index.js +23 -0
  132. package/dist/oauth/components/FigmaAvatarCell/index.scss +5 -0
  133. package/dist/oauth/components/FigmaAvatarPlaceholder/index.d.ts +8 -0
  134. package/dist/oauth/components/FigmaAvatarPlaceholder/index.js +35 -0
  135. package/dist/oauth/components/FigmaAvatarPlaceholder/index.scss +28 -0
  136. package/dist/oauth/components/LoginButton/iframeAutoLogin.d.ts +81 -0
  137. package/dist/oauth/components/LoginButton/iframeAutoLogin.js +168 -0
  138. package/dist/oauth/components/LoginButton/index.d.ts +0 -1
  139. package/dist/oauth/components/LoginButton/index.js +156 -18
  140. package/dist/oauth/components/LoginButton/index.scss +75 -3
  141. package/dist/oauth/components/LogoutButton/index.d.ts +0 -1
  142. package/dist/oauth/components/LogoutButton/index.js +20 -9
  143. package/dist/oauth/defaults.d.ts +3 -2
  144. package/dist/oauth/defaults.js +79 -12
  145. package/dist/oauth/endpoints/getLoginEndpoint.d.ts +0 -1
  146. package/dist/oauth/endpoints/getLoginEndpoint.js +87 -84
  147. package/dist/oauth/endpoints/getLogoutEndpoint.d.ts +0 -1
  148. package/dist/oauth/endpoints/getLogoutEndpoint.js +7 -6
  149. package/dist/oauth/endpoints/getMetaEndpoint.d.ts +0 -1
  150. package/dist/oauth/endpoints/getMetaEndpoint.js +18 -5
  151. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.d.ts +0 -1
  152. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js +11 -4
  153. package/dist/oauth/exports/client.d.ts +0 -1
  154. package/dist/oauth/exports/client.js +0 -2
  155. package/dist/oauth/hooks/afterLogout.d.ts +0 -1
  156. package/dist/oauth/hooks/afterLogout.js +0 -2
  157. package/dist/oauth/hooks/me.d.ts +0 -1
  158. package/dist/oauth/hooks/me.js +0 -2
  159. package/dist/oauth/hooks/refresh.d.ts +0 -1
  160. package/dist/oauth/hooks/refresh.js +2 -3
  161. package/dist/oauth/index.d.ts +0 -1
  162. package/dist/oauth/index.js +27 -7
  163. package/dist/oauth/strategy/index.d.ts +0 -3
  164. package/dist/oauth/strategy/index.js +55 -34
  165. package/dist/oauth/types.d.ts +23 -7
  166. package/dist/oauth/types.js +0 -2
  167. package/dist/oauth/utilities/buildUnauthorizedRedirect.d.ts +14 -0
  168. package/dist/oauth/utilities/buildUnauthorizedRedirect.js +28 -0
  169. package/dist/oauth/utilities/clearCookie.d.ts +0 -1
  170. package/dist/oauth/utilities/clearCookie.js +5 -3
  171. package/dist/oauth/utilities/createCookieOptions.d.ts +0 -1
  172. package/dist/oauth/utilities/createCookieOptions.js +9 -4
  173. package/dist/oauth/utilities/createDebugLogger.d.ts +0 -1
  174. package/dist/oauth/utilities/createDebugLogger.js +0 -2
  175. package/dist/oauth/utilities/establishSession.d.ts +22 -0
  176. package/dist/oauth/utilities/establishSession.js +80 -0
  177. package/dist/oauth/utilities/exchangeCodeForAccessToken.d.ts +23 -0
  178. package/dist/oauth/utilities/exchangeCodeForAccessToken.js +26 -0
  179. package/dist/oauth/utilities/extractOrigin.d.ts +0 -1
  180. package/dist/oauth/utilities/extractOrigin.js +0 -2
  181. package/dist/oauth/utilities/figmaHostnames.d.ts +2 -0
  182. package/dist/oauth/utilities/figmaHostnames.js +24 -0
  183. package/dist/oauth/utilities/getAdminCollectionSlug.d.ts +0 -1
  184. package/dist/oauth/utilities/getAdminCollectionSlug.js +0 -2
  185. package/dist/oauth/utilities/getAuthorizeURL.d.ts +65 -2
  186. package/dist/oauth/utilities/getAuthorizeURL.js +57 -4
  187. package/dist/oauth/utilities/getCookieExpiration.d.ts +0 -1
  188. package/dist/oauth/utilities/getCookieExpiration.js +0 -2
  189. package/dist/oauth/utilities/getSecondsFromTokenExp.d.ts +0 -1
  190. package/dist/oauth/utilities/getSecondsFromTokenExp.js +0 -2
  191. package/dist/oauth/utilities/getTokenExp.d.ts +0 -1
  192. package/dist/oauth/utilities/getTokenExp.js +0 -2
  193. package/dist/oauth/utilities/getUsernameField.d.ts +0 -1
  194. package/dist/oauth/utilities/getUsernameField.js +0 -2
  195. package/dist/oauth/utilities/hasUserTokenPropsChanged.d.ts +0 -1
  196. package/dist/oauth/utilities/hasUserTokenPropsChanged.js +0 -2
  197. package/dist/oauth/utilities/isAbsoluteURL.d.ts +1 -0
  198. package/dist/oauth/utilities/isAbsoluteURL.js +1 -0
  199. package/dist/oauth/utilities/isDuplicateKeyError.d.ts +6 -0
  200. package/dist/oauth/utilities/isDuplicateKeyError.js +12 -0
  201. package/dist/oauth/utilities/mergeHeaders.d.ts +0 -1
  202. package/dist/oauth/utilities/mergeHeaders.js +0 -2
  203. package/dist/oauth/utilities/refreshTokens.d.ts +0 -1
  204. package/dist/oauth/utilities/refreshTokens.js +21 -13
  205. package/dist/oauth/utilities/withPartitionedCookie.d.ts +19 -0
  206. package/dist/oauth/utilities/withPartitionedCookie.js +26 -0
  207. package/dist/oauth/utils/getSearchParam.d.ts +17 -0
  208. package/dist/oauth/utils/getSearchParam.js +22 -0
  209. package/dist/plugin/adapter.d.ts +0 -1
  210. package/dist/plugin/adapter.js +0 -2
  211. package/dist/plugin/auth-preflight.d.ts +7 -0
  212. package/dist/plugin/auth-preflight.js +18 -0
  213. package/dist/plugin/bootstrap-preflight.d.ts +22 -0
  214. package/dist/plugin/bootstrap-preflight.js +43 -0
  215. package/dist/plugin/build-config.d.ts +27 -15
  216. package/dist/plugin/build-config.js +381 -18
  217. package/dist/plugin/dev-cookie-names.d.ts +13 -0
  218. package/dist/plugin/dev-cookie-names.js +17 -0
  219. package/dist/scss.d.js +2 -0
  220. package/dist/storage-content-api/api-types.d.ts +183 -0
  221. package/dist/storage-content-api/api-types.js +4 -0
  222. package/dist/storage-content-api/client-uploads/generate.d.ts +14 -0
  223. package/dist/storage-content-api/client-uploads/generate.js +69 -0
  224. package/dist/storage-content-api/client.d.ts +5 -0
  225. package/dist/storage-content-api/client.js +37 -0
  226. package/dist/storage-content-api/generateURL.d.ts +6 -0
  227. package/dist/storage-content-api/generateURL.js +6 -0
  228. package/dist/storage-content-api/handleDelete.d.ts +7 -0
  229. package/dist/storage-content-api/handleDelete.js +15 -0
  230. package/dist/storage-content-api/handleUpload.d.ts +10 -0
  231. package/dist/storage-content-api/handleUpload.js +162 -0
  232. package/dist/storage-content-api/index.d.ts +4 -0
  233. package/dist/storage-content-api/index.js +37 -0
  234. package/dist/storage-content-api/staticHandler.d.ts +9 -0
  235. package/dist/storage-content-api/staticHandler.js +61 -0
  236. package/dist/storage-content-api/types.d.ts +9 -0
  237. package/dist/storage-content-api/types.js +1 -0
  238. package/dist/storage-content-api/utilities/getSafeFilename.d.ts +11 -0
  239. package/dist/storage-content-api/utilities/getSafeFilename.js +59 -0
  240. package/dist/storage-content-api/utilities/index.d.ts +2 -0
  241. package/dist/storage-content-api/utilities/index.js +2 -0
  242. package/dist/storage-content-api/utilities/parseUploadReference.d.ts +17 -0
  243. package/dist/storage-content-api/utilities/parseUploadReference.js +27 -0
  244. package/dist/templates/.env.example +5 -0
  245. package/dist/templates/README.md +19 -0
  246. package/dist/types/config.d.ts +2 -2
  247. package/dist/types/config.js +0 -4
  248. package/dist/types.d.ts +10 -2
  249. package/dist/types.js +0 -2
  250. package/dist/utils/adapters/nextjs.d.ts +8 -0
  251. package/dist/utils/adapters/nextjs.js +61 -0
  252. package/dist/utils/adapters/nitro.d.ts +8 -0
  253. package/dist/utils/adapters/nitro.js +172 -0
  254. package/dist/utils/adapters/vite.d.ts +9 -0
  255. package/dist/utils/adapters/vite.js +31 -0
  256. package/dist/utils/asset-collection.d.ts +27 -7
  257. package/dist/utils/asset-collection.js +59 -32
  258. package/dist/utils/build-detection.d.ts +5 -12
  259. package/dist/utils/build-detection.js +74 -13
  260. package/dist/utils/build-lambda-zip.d.ts +25 -0
  261. package/dist/utils/build-lambda-zip.js +90 -0
  262. package/dist/utils/cache-bootstrap.d.ts +7 -0
  263. package/dist/utils/cache-bootstrap.js +16 -0
  264. package/dist/utils/config.d.ts +0 -1
  265. package/dist/utils/config.js +1 -3
  266. package/dist/utils/deploy-adapter.d.ts +45 -0
  267. package/dist/utils/deploy-adapter.js +56 -0
  268. package/dist/utils/download-template.d.ts +9 -2
  269. package/dist/utils/download-template.js +24 -20
  270. package/dist/utils/env-management.d.ts +24 -8
  271. package/dist/utils/env-management.js +119 -66
  272. package/dist/utils/format-env-suffix.d.ts +11 -0
  273. package/dist/utils/format-env-suffix.js +11 -0
  274. package/dist/utils/format.d.ts +0 -1
  275. package/dist/utils/format.js +0 -2
  276. package/dist/utils/formatter.d.ts +0 -1
  277. package/dist/utils/formatter.js +23 -13
  278. package/dist/utils/fs-utils.d.ts +12 -0
  279. package/dist/utils/fs-utils.js +55 -0
  280. package/dist/utils/git.d.ts +0 -1
  281. package/dist/utils/git.js +0 -2
  282. package/dist/utils/handle-upgrade.d.ts +8 -0
  283. package/dist/utils/handle-upgrade.js +39 -0
  284. package/dist/utils/is-debug.d.ts +0 -1
  285. package/dist/utils/is-debug.js +0 -2
  286. package/dist/utils/lambda-config.d.ts +3 -2
  287. package/dist/utils/lambda-config.js +75 -80
  288. package/dist/utils/load-payload-config.d.ts +9 -0
  289. package/dist/utils/load-payload-config.js +27 -0
  290. package/dist/utils/log.d.ts +0 -1
  291. package/dist/utils/log.js +0 -2
  292. package/dist/utils/messages.d.ts +1 -3
  293. package/dist/utils/messages.js +47 -13
  294. package/dist/utils/package-manager.d.ts +24 -1
  295. package/dist/utils/package-manager.js +53 -2
  296. package/dist/utils/parse-template-spec.d.ts +11 -0
  297. package/dist/utils/parse-template-spec.js +60 -0
  298. package/dist/utils/payload-config-ast.d.ts +27 -7
  299. package/dist/utils/payload-config-ast.js +106 -60
  300. package/dist/utils/payload-config-finder.d.ts +2 -3
  301. package/dist/utils/payload-config-finder.js +48 -11
  302. package/dist/utils/payload-config-modifier.d.ts +1 -2
  303. package/dist/utils/payload-config-modifier.js +114 -68
  304. package/dist/utils/payload-package-check.d.ts +28 -3
  305. package/dist/utils/payload-package-check.js +90 -31
  306. package/dist/utils/project.d.ts +8 -4
  307. package/dist/utils/project.js +63 -37
  308. package/dist/utils/resolve-environment.d.ts +13 -0
  309. package/dist/utils/resolve-environment.js +29 -0
  310. package/dist/utils/s3-upload.d.ts +7 -3
  311. package/dist/utils/s3-upload.js +44 -9
  312. package/dist/utils/token-display.d.ts +5 -2
  313. package/dist/utils/token-display.js +49 -24
  314. package/dist/utils/typescript-validator.d.ts +0 -1
  315. package/dist/utils/typescript-validator.js +4 -8
  316. package/dist/utils/version-check.d.ts +2 -0
  317. package/dist/utils/version-check.js +43 -0
  318. package/package.json +47 -16
  319. package/dist/api/control-plane.d.ts.map +0 -1
  320. package/dist/api/control-plane.js.map +0 -1
  321. package/dist/api/figma-api.d.ts.map +0 -1
  322. package/dist/api/figma-api.js.map +0 -1
  323. package/dist/auth/browser.d.ts.map +0 -1
  324. package/dist/auth/browser.js.map +0 -1
  325. package/dist/auth/callback-server.d.ts.map +0 -1
  326. package/dist/auth/callback-server.js.map +0 -1
  327. package/dist/auth/crypto-utils.d.ts.map +0 -1
  328. package/dist/auth/crypto-utils.js.map +0 -1
  329. package/dist/auth/jwt-validator.d.ts.map +0 -1
  330. package/dist/auth/jwt-validator.js.map +0 -1
  331. package/dist/auth/oauth-flow.d.ts.map +0 -1
  332. package/dist/auth/oauth-flow.js.map +0 -1
  333. package/dist/auth/pkce.d.ts.map +0 -1
  334. package/dist/auth/pkce.js.map +0 -1
  335. package/dist/auth/project-token.d.ts.map +0 -1
  336. package/dist/auth/project-token.js.map +0 -1
  337. package/dist/auth/refresh.d.ts.map +0 -1
  338. package/dist/auth/refresh.js.map +0 -1
  339. package/dist/auth/token-store.d.ts.map +0 -1
  340. package/dist/auth/token-store.js.map +0 -1
  341. package/dist/auth/types.d.ts.map +0 -1
  342. package/dist/auth/types.js.map +0 -1
  343. package/dist/cli.d.ts.map +0 -1
  344. package/dist/cli.js.map +0 -1
  345. package/dist/commands/deploy.d.ts.map +0 -1
  346. package/dist/commands/deploy.js.map +0 -1
  347. package/dist/commands/init.d.ts.map +0 -1
  348. package/dist/commands/init.js.map +0 -1
  349. package/dist/commands/list-tokens.d.ts.map +0 -1
  350. package/dist/commands/list-tokens.js.map +0 -1
  351. package/dist/commands/login.d.ts.map +0 -1
  352. package/dist/commands/login.js.map +0 -1
  353. package/dist/commands/logout.d.ts.map +0 -1
  354. package/dist/commands/logout.js.map +0 -1
  355. package/dist/config/oauth.d.ts.map +0 -1
  356. package/dist/config/oauth.js.map +0 -1
  357. package/dist/constants.d.ts.map +0 -1
  358. package/dist/constants.js.map +0 -1
  359. package/dist/exports/client.d.ts.map +0 -1
  360. package/dist/exports/client.js.map +0 -1
  361. package/dist/index.d.ts.map +0 -1
  362. package/dist/index.js.map +0 -1
  363. package/dist/oauth/components/LoginButton/index.d.ts.map +0 -1
  364. package/dist/oauth/components/LoginButton/index.js.map +0 -1
  365. package/dist/oauth/components/LogoutButton/index.d.ts.map +0 -1
  366. package/dist/oauth/components/LogoutButton/index.js.map +0 -1
  367. package/dist/oauth/defaults.d.ts.map +0 -1
  368. package/dist/oauth/defaults.js.map +0 -1
  369. package/dist/oauth/endpoints/getLoginEndpoint.d.ts.map +0 -1
  370. package/dist/oauth/endpoints/getLoginEndpoint.js.map +0 -1
  371. package/dist/oauth/endpoints/getLogoutEndpoint.d.ts.map +0 -1
  372. package/dist/oauth/endpoints/getLogoutEndpoint.js.map +0 -1
  373. package/dist/oauth/endpoints/getMetaEndpoint.d.ts.map +0 -1
  374. package/dist/oauth/endpoints/getMetaEndpoint.js.map +0 -1
  375. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.d.ts.map +0 -1
  376. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js.map +0 -1
  377. package/dist/oauth/exports/client.d.ts.map +0 -1
  378. package/dist/oauth/exports/client.js.map +0 -1
  379. package/dist/oauth/hooks/afterLogout.d.ts.map +0 -1
  380. package/dist/oauth/hooks/afterLogout.js.map +0 -1
  381. package/dist/oauth/hooks/me.d.ts.map +0 -1
  382. package/dist/oauth/hooks/me.js.map +0 -1
  383. package/dist/oauth/hooks/refresh.d.ts.map +0 -1
  384. package/dist/oauth/hooks/refresh.js.map +0 -1
  385. package/dist/oauth/index.d.ts.map +0 -1
  386. package/dist/oauth/index.js.map +0 -1
  387. package/dist/oauth/strategy/index.d.ts.map +0 -1
  388. package/dist/oauth/strategy/index.js.map +0 -1
  389. package/dist/oauth/types.d.ts.map +0 -1
  390. package/dist/oauth/types.js.map +0 -1
  391. package/dist/oauth/utilities/clearCookie.d.ts.map +0 -1
  392. package/dist/oauth/utilities/clearCookie.js.map +0 -1
  393. package/dist/oauth/utilities/createCookieOptions.d.ts.map +0 -1
  394. package/dist/oauth/utilities/createCookieOptions.js.map +0 -1
  395. package/dist/oauth/utilities/createDebugLogger.d.ts.map +0 -1
  396. package/dist/oauth/utilities/createDebugLogger.js.map +0 -1
  397. package/dist/oauth/utilities/extractOrigin.d.ts.map +0 -1
  398. package/dist/oauth/utilities/extractOrigin.js.map +0 -1
  399. package/dist/oauth/utilities/getAdminCollectionSlug.d.ts.map +0 -1
  400. package/dist/oauth/utilities/getAdminCollectionSlug.js.map +0 -1
  401. package/dist/oauth/utilities/getAdminPath.d.ts +0 -8
  402. package/dist/oauth/utilities/getAdminPath.d.ts.map +0 -1
  403. package/dist/oauth/utilities/getAdminPath.js +0 -9
  404. package/dist/oauth/utilities/getAdminPath.js.map +0 -1
  405. package/dist/oauth/utilities/getAuthorizeURL.d.ts.map +0 -1
  406. package/dist/oauth/utilities/getAuthorizeURL.js.map +0 -1
  407. package/dist/oauth/utilities/getCookieExpiration.d.ts.map +0 -1
  408. package/dist/oauth/utilities/getCookieExpiration.js.map +0 -1
  409. package/dist/oauth/utilities/getSecondsFromTokenExp.d.ts.map +0 -1
  410. package/dist/oauth/utilities/getSecondsFromTokenExp.js.map +0 -1
  411. package/dist/oauth/utilities/getTokenExp.d.ts.map +0 -1
  412. package/dist/oauth/utilities/getTokenExp.js.map +0 -1
  413. package/dist/oauth/utilities/getUsernameField.d.ts.map +0 -1
  414. package/dist/oauth/utilities/getUsernameField.js.map +0 -1
  415. package/dist/oauth/utilities/hasUserTokenPropsChanged.d.ts.map +0 -1
  416. package/dist/oauth/utilities/hasUserTokenPropsChanged.js.map +0 -1
  417. package/dist/oauth/utilities/mergeHeaders.d.ts.map +0 -1
  418. package/dist/oauth/utilities/mergeHeaders.js.map +0 -1
  419. package/dist/oauth/utilities/refreshTokens.d.ts.map +0 -1
  420. package/dist/oauth/utilities/refreshTokens.js.map +0 -1
  421. package/dist/plugin/adapter.d.ts.map +0 -1
  422. package/dist/plugin/adapter.js.map +0 -1
  423. package/dist/plugin/build-config.d.ts.map +0 -1
  424. package/dist/plugin/build-config.js.map +0 -1
  425. package/dist/types/config.d.ts.map +0 -1
  426. package/dist/types/config.js.map +0 -1
  427. package/dist/types.d.ts.map +0 -1
  428. package/dist/types.js.map +0 -1
  429. package/dist/utils/asset-collection.d.ts.map +0 -1
  430. package/dist/utils/asset-collection.js.map +0 -1
  431. package/dist/utils/build-detection.d.ts.map +0 -1
  432. package/dist/utils/build-detection.js.map +0 -1
  433. package/dist/utils/config.d.ts.map +0 -1
  434. package/dist/utils/config.js.map +0 -1
  435. package/dist/utils/download-template.d.ts.map +0 -1
  436. package/dist/utils/download-template.js.map +0 -1
  437. package/dist/utils/env-management.d.ts.map +0 -1
  438. package/dist/utils/env-management.js.map +0 -1
  439. package/dist/utils/format.d.ts.map +0 -1
  440. package/dist/utils/format.js.map +0 -1
  441. package/dist/utils/formatter.d.ts.map +0 -1
  442. package/dist/utils/formatter.js.map +0 -1
  443. package/dist/utils/git.d.ts.map +0 -1
  444. package/dist/utils/git.js.map +0 -1
  445. package/dist/utils/is-debug.d.ts.map +0 -1
  446. package/dist/utils/is-debug.js.map +0 -1
  447. package/dist/utils/lambda-config.d.ts.map +0 -1
  448. package/dist/utils/lambda-config.js.map +0 -1
  449. package/dist/utils/log.d.ts.map +0 -1
  450. package/dist/utils/log.js.map +0 -1
  451. package/dist/utils/messages.d.ts.map +0 -1
  452. package/dist/utils/messages.js.map +0 -1
  453. package/dist/utils/package-manager.d.ts.map +0 -1
  454. package/dist/utils/package-manager.js.map +0 -1
  455. package/dist/utils/payload-config-ast.d.ts.map +0 -1
  456. package/dist/utils/payload-config-ast.js.map +0 -1
  457. package/dist/utils/payload-config-finder.d.ts.map +0 -1
  458. package/dist/utils/payload-config-finder.js.map +0 -1
  459. package/dist/utils/payload-config-modifier.d.ts.map +0 -1
  460. package/dist/utils/payload-config-modifier.js.map +0 -1
  461. package/dist/utils/payload-package-check.d.ts.map +0 -1
  462. package/dist/utils/payload-package-check.js.map +0 -1
  463. package/dist/utils/project.d.ts.map +0 -1
  464. package/dist/utils/project.js.map +0 -1
  465. package/dist/utils/s3-upload.d.ts.map +0 -1
  466. package/dist/utils/s3-upload.js.map +0 -1
  467. package/dist/utils/token-display.d.ts.map +0 -1
  468. package/dist/utils/token-display.js.map +0 -1
  469. package/dist/utils/typescript-validator.d.ts.map +0 -1
  470. package/dist/utils/typescript-validator.js.map +0 -1
@@ -1,11 +1,12 @@
1
+ import type { Environment } from '../constants.js';
1
2
  import type { JWTPayload } from './types.js';
2
3
  /**
3
4
  * JWT validation error with specific error codes
4
5
  */
5
6
  export declare class JWTValidationError extends Error {
6
- code: 'EXPIRED' | 'JWKS_FETCH_FAILED' | 'MISSING_KID' | 'SIGNATURE_INVALID';
7
+ code: 'AUDIENCE_INVALID' | 'EXPIRED' | 'JWKS_FETCH_FAILED' | 'MISSING_KID' | 'SIGNATURE_INVALID' | 'TOKEN_CLAIMS_INVALID';
7
8
  cause?: Error | undefined;
8
- constructor(message: string, code: 'EXPIRED' | 'JWKS_FETCH_FAILED' | 'MISSING_KID' | 'SIGNATURE_INVALID', cause?: Error | undefined);
9
+ constructor(message: string, code: 'AUDIENCE_INVALID' | 'EXPIRED' | 'JWKS_FETCH_FAILED' | 'MISSING_KID' | 'SIGNATURE_INVALID' | 'TOKEN_CLAIMS_INVALID', cause?: Error | undefined);
9
10
  }
10
11
  /**
11
12
  * Validate a project token JWT
@@ -22,12 +23,29 @@ export declare class JWTValidationError extends Error {
22
23
  * - Validates standard claims (exp, iat, nbf)
23
24
  * - Handles clock skew tolerance
24
25
  *
25
- * @param token - JWT token string
26
- * @param environment - Figma environment ('production' or 'staging')
26
+ * @param params.token - JWT token string
27
+ * @param params.environment - Figma environment ('production' or 'staging')
28
+ * @param params.audience - Expected `aud` claim (the tenant's contentSystemId);
29
+ * when provided, jose rejects tokens whose `aud` does not match
27
30
  * @returns Promise resolving to validated JWT payload
28
31
  * @throws {JWTValidationError} If validation fails
29
32
  */
30
- export declare function validateProjectToken(token: string, environment: 'production' | 'staging'): Promise<JWTPayload>;
33
+ export declare function validateProjectToken(params: {
34
+ /** Expected `aud` claim — the tenant's contentSystemId. Enforced when provided. */
35
+ audience?: string;
36
+ environment: Environment;
37
+ token: string;
38
+ }): Promise<JWTPayload>;
39
+ export declare function validatePayloadAdminToken(params: {
40
+ audience: string;
41
+ environment: Environment;
42
+ token: string;
43
+ }): Promise<JWTPayload>;
44
+ export declare function validateContentApiToken(params: {
45
+ audience: string;
46
+ environment: Environment;
47
+ token: string;
48
+ }): Promise<JWTPayload>;
31
49
  /**
32
50
  * Clear JWKS cache (useful for testing or forcing refresh)
33
51
  *
@@ -38,4 +56,3 @@ export declare function validateProjectToken(token: string, environment: 'produc
38
56
  * - Clearing state between test runs
39
57
  */
40
58
  export declare function clearJWKSCache(): void;
41
- //# sourceMappingURL=jwt-validator.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import { createRemoteJWKSet, jwtVerify } from 'jose';
2
- import { JWKSMultipleMatchingKeys, JWKSNoMatchingKey, JWSInvalid, JWSSignatureVerificationFailed, JWTExpired } from 'jose/errors';
3
- import { getJWKSUri } from '../constants.js';
2
+ import { JWKSMultipleMatchingKeys, JWKSNoMatchingKey, JWSInvalid, JWSSignatureVerificationFailed, JWTClaimValidationFailed, JWTExpired } from 'jose/errors';
3
+ import { getEnvConfig } from '../constants.js';
4
4
  /**
5
5
  * JWT validation error with specific error codes
6
6
  */ export class JWTValidationError extends Error {
@@ -28,7 +28,7 @@ import { getJWKSUri } from '../constants.js';
28
28
  * @param environment - Figma environment ('production' or 'staging')
29
29
  * @returns JWKS resolver function
30
30
  */ function getJWKSResolver(environment) {
31
- const jwksUri = getJWKSUri(environment);
31
+ const jwksUri = getEnvConfig(environment).jwksUri;
32
32
  if (!jwksResolvers.has(jwksUri)) {
33
33
  jwksResolvers.set(jwksUri, createRemoteJWKSet(new URL(jwksUri), {
34
34
  cacheMaxAge: 24 * 60 * 60 * 1000,
@@ -52,15 +52,21 @@ import { getJWKSUri } from '../constants.js';
52
52
  * - Validates standard claims (exp, iat, nbf)
53
53
  * - Handles clock skew tolerance
54
54
  *
55
- * @param token - JWT token string
56
- * @param environment - Figma environment ('production' or 'staging')
55
+ * @param params.token - JWT token string
56
+ * @param params.environment - Figma environment ('production' or 'staging')
57
+ * @param params.audience - Expected `aud` claim (the tenant's contentSystemId);
58
+ * when provided, jose rejects tokens whose `aud` does not match
57
59
  * @returns Promise resolving to validated JWT payload
58
60
  * @throws {JWTValidationError} If validation fails
59
- */ export async function validateProjectToken(token, environment) {
61
+ */ export async function validateProjectToken(params) {
62
+ const { audience, environment, token } = params;
60
63
  try {
61
64
  const JWKS = getJWKSResolver(environment);
62
65
  const { payload } = await jwtVerify(token, JWKS, {
63
- clockTolerance: 300
66
+ clockTolerance: 30,
67
+ ...audience ? {
68
+ audience
69
+ } : {}
64
70
  });
65
71
  return payload;
66
72
  } catch (error) {
@@ -86,6 +92,10 @@ import { getJWKSUri } from '../constants.js';
86
92
  if (error instanceof JWSInvalid) {
87
93
  throw new JWTValidationError('Invalid JWT structure - missing required header fields (kid or alg)', 'MISSING_KID', error);
88
94
  }
95
+ // Audience mismatch (or missing `aud` when an audience is required)
96
+ if (error instanceof JWTClaimValidationFailed && error.claim === 'aud') {
97
+ throw new JWTValidationError('Token audience does not match this tenant', 'AUDIENCE_INVALID', error);
98
+ }
89
99
  // Network or fetch errors (not jose errors, generic Error instances)
90
100
  if (error instanceof Error) {
91
101
  const message = error.message;
@@ -98,6 +108,24 @@ import { getJWKSUri } from '../constants.js';
98
108
  throw new JWTValidationError(`JWT validation failed: ${message}`, 'SIGNATURE_INVALID', error instanceof Error ? error : undefined);
99
109
  }
100
110
  }
111
+ export async function validatePayloadAdminToken(params) {
112
+ const payload = await validateProjectToken({
113
+ ...params,
114
+ audience: `eid_${params.audience}`
115
+ });
116
+ if (typeof payload.sub !== 'string' || typeof payload.email !== 'string') {
117
+ throw new JWTValidationError('Payload Admin token claims are invalid', 'TOKEN_CLAIMS_INVALID');
118
+ }
119
+ return payload;
120
+ }
121
+ export async function validateContentApiToken(params) {
122
+ // Content API tokens are issued by the content-system-scoped endpoint, which
123
+ // prefixes the `aud` with `csid_` (mirrors the `eid_` admin-token scoping).
124
+ return validateProjectToken({
125
+ ...params,
126
+ audience: `csid_${params.audience}`
127
+ });
128
+ }
101
129
  /**
102
130
  * Clear JWKS cache (useful for testing or forcing refresh)
103
131
  *
@@ -109,5 +137,3 @@ import { getJWKSUri } from '../constants.js';
109
137
  */ export function clearJWKSCache() {
110
138
  jwksResolvers.clear();
111
139
  }
112
-
113
- //# sourceMappingURL=jwt-validator.js.map
@@ -1,3 +1,4 @@
1
+ import type { AuthCredential } from './credentials.js';
1
2
  import type { TokenStore } from './token-store.js';
2
3
  import type { FigmaTokens } from './types.js';
3
4
  /**
@@ -13,7 +14,9 @@ export declare class OAuthFlowError extends Error {
13
14
  export interface OAuthFlowOptions {
14
15
  /** OAuth2 client ID (defaults to config) */
15
16
  clientId?: string;
16
- /** Callback server port (defaults to 3000) */
17
+ /** Callback server fallback ports to try after port */
18
+ fallbackPorts?: number[];
19
+ /** First callback server port to try */
17
20
  port?: number;
18
21
  /** Redirect URI (defaults to config) */
19
22
  redirectUri?: string;
@@ -55,8 +58,20 @@ export declare function executeOAuthFlow(tokenStore: TokenStore, options?: OAuth
55
58
  * refreshes using the refresh token. If no tokens exist, returns null.
56
59
  *
57
60
  * @param tokenStore - Token store to use
58
- * @returns Promise resolving to access token or null if no valid tokens
61
+ * @returns Promise resolving to AuthCredential (wrapped access token) or null if no valid tokens
59
62
  * @throws OAuthFlowError if refresh fails
60
63
  */
61
- export declare function getValidAccessToken(tokenStore: TokenStore): Promise<null | string>;
62
- //# sourceMappingURL=oauth-flow.d.ts.map
64
+ export declare function getValidOAuthAccessToken(tokenStore: TokenStore): Promise<AuthCredential | null>;
65
+ /**
66
+ * Get a valid auth credential, checking process.env for plan access token
67
+ * first before checking tokenStore for OAuth tokens.
68
+ * *
69
+ * @param tokenStore - Token store to use for OAuth tokens
70
+ * @returns Promise resolving to AuthCredential or null
71
+ */
72
+ export declare function getValidCredential(tokenStore: TokenStore): Promise<AuthCredential | null>;
73
+ /**
74
+ * Like getValidCredential but returns null instead of throwing on refresh failure.
75
+ * Use in commands that want to fall through to a login prompt on failure.
76
+ */
77
+ export declare function tryGetCredential(tokenStore: TokenStore): Promise<AuthCredential | null>;
@@ -1,11 +1,12 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import crypto from 'crypto';
3
- import { OAUTH_CONFIG } from '../config/oauth.js';
3
+ import { getOAuthConfig } from '../config/oauth.js';
4
4
  import * as log from '../utils/log.js';
5
5
  import { buildAuthorizationUrl, openBrowser } from './browser.js';
6
- import { CallbackServer } from './callback-server.js';
6
+ import { CallbackError, CallbackServer } from './callback-server.js';
7
+ import { parsePastedCode, validatePastedCode } from './paste-code.js';
7
8
  import { generatePKCEPair } from './pkce.js';
8
- import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
9
+ import { exchangeCodeForTokens, refreshAccessToken, TokenRefreshError } from './refresh.js';
9
10
  /**
10
11
  * Error during OAuth flow
11
12
  */ export class OAuthFlowError extends Error {
@@ -32,16 +33,17 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
32
33
  * @throws OAuthFlowError if any step fails
33
34
  */ export async function executeOAuthFlow(tokenStore, options = {}) {
34
35
  // Check if OAuth flow should be mocked
35
- // Default to true for OAuth (allow testing without real authentication by default)
36
- const shouldMock = process.env.FIGMA_MOCK_OAUTH !== 'false';
36
+ // Default to false for OAuth
37
+ const shouldMock = process.env.FIGMA_MOCK_OAUTH === 'true';
38
+ const oauthConfig = getOAuthConfig();
37
39
  if (shouldMock) {
38
40
  // MOCK IMPLEMENTATION: Return mock tokens for testing
39
- log.debug('Using mock OAuth flow (FIGMA_MOCK_OAUTH != "false")');
41
+ log.debug('Using mock OAuth flow (FIGMA_MOCK_OAUTH = true)');
40
42
  const mockTokens = {
41
43
  accessToken: 'figt_mock_access_token_' + crypto.randomBytes(16).toString('hex'),
42
44
  expiresAt: Date.now() + 2 * 60 * 60 * 1000,
43
45
  refreshToken: 'figt_mock_refresh_token_' + crypto.randomBytes(16).toString('hex'),
44
- scopes: options.scopes || OAUTH_CONFIG.scopes,
46
+ scopes: options.scopes || oauthConfig.scopes,
45
47
  tokenType: 'Bearer'
46
48
  };
47
49
  // Store mock tokens
@@ -52,28 +54,30 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
52
54
  };
53
55
  }
54
56
  // REAL OAUTH IMPLEMENTATION
55
- const { clientId = OAUTH_CONFIG.clientId, port = 3000, redirectUri = OAUTH_CONFIG.redirectUri, scopes = OAUTH_CONFIG.scopes, timeoutMs = 120000 } = options;
57
+ const { clientId = oauthConfig.clientId, fallbackPorts, port, redirectUri = oauthConfig.redirectUri, scopes = oauthConfig.scopes, timeoutMs = 120000 } = options;
56
58
  // Generate PKCE pair for enhanced security
57
59
  const { codeChallenge, codeChallengeMethod, codeVerifier } = generatePKCEPair();
58
60
  // Generate random state for CSRF protection
59
61
  const state = crypto.randomBytes(32).toString('base64url');
60
62
  // Create callback server
61
63
  const callbackServer = new CallbackServer({
64
+ fallbackPorts,
62
65
  port,
63
66
  timeoutMs
64
67
  });
65
68
  try {
66
69
  // Start waiting for callback (this starts the server and captures actual port)
67
70
  const callbackPromise = callbackServer.waitForCallback(state);
68
- // Wait a bit for server to start and determine actual port
69
- await new Promise((resolve)=>setTimeout(resolve, 100));
71
+ callbackPromise.catch(()=>{
72
+ // The callback promise is awaited below; avoid an unhandled rejection if startup fails early.
73
+ });
70
74
  // Get the actual port (may differ from preferred if that was in use)
71
- const actualPort = callbackServer.getActualPort();
75
+ const actualPort = await callbackServer.waitUntilReady();
72
76
  // Build redirect URI with actual port
73
- const actualRedirectUri = redirectUri.replace(/:\d+/, `:${actualPort}`);
77
+ const actualRedirectUri = replaceRedirectUriPort(redirectUri, actualPort);
74
78
  // Build authorization URL
75
79
  const authUrl = buildAuthorizationUrl({
76
- authorizationUrl: OAUTH_CONFIG.authorizationUrl,
80
+ authorizationUrl: oauthConfig.authorizationUrl,
77
81
  clientId,
78
82
  codeChallenge,
79
83
  codeChallengeMethod,
@@ -84,28 +88,36 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
84
88
  // Prompt user to open browser
85
89
  const shouldOpenBrowser = await p.confirm({
86
90
  initialValue: true,
87
- message: 'Log in or create Figma account in your browser?'
91
+ message: 'Open browser to authenticate with Figma?'
88
92
  });
89
93
  if (p.isCancel(shouldOpenBrowser)) {
90
94
  throw new OAuthFlowError('Authentication cancelled by user');
91
95
  }
96
+ let browserOpened = false;
92
97
  if (shouldOpenBrowser) {
93
- // Try to open browser, but don't fail if it doesn't work
94
98
  try {
95
99
  await openBrowser(authUrl);
100
+ browserOpened = true;
96
101
  } catch (_error) {
97
- // Browser opening failed, show URL for manual opening
98
102
  log.warning('Could not open browser automatically.');
99
- log.info(`Please open this URL in your browser:`);
100
- log.info(` ${authUrl}`);
101
103
  }
104
+ }
105
+ let code;
106
+ if (browserOpened) {
107
+ // Browser launched locally; the localhost listener receives the callback.
108
+ code = (await callbackPromise).code;
102
109
  } else {
103
- // User declined automatic opening, show URL
104
- log.info(`Please open this URL manually in your browser:`);
105
- log.info(` ${authUrl}`);
110
+ // No local browser (user declined, or open() failed — e.g. a remote devbox).
111
+ // Show the URL to open manually and accept the redirected code pasted back,
112
+ // while the localhost listener keeps running in case it can still receive it.
113
+ // p.log.step directly (not log.info) to avoid bolding the URL.
114
+ p.log.step(`Open this URL to authenticate:\n\n ${authUrl}`);
115
+ code = await waitForCallbackOrPastedCode({
116
+ callbackPromise,
117
+ callbackServer,
118
+ expectedState: state
119
+ });
106
120
  }
107
- // Wait for callback
108
- const { code } = await callbackPromise;
109
121
  // Exchange authorization code for tokens
110
122
  let tokens;
111
123
  try {
@@ -142,28 +154,133 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
142
154
  * refreshes using the refresh token. If no tokens exist, returns null.
143
155
  *
144
156
  * @param tokenStore - Token store to use
145
- * @returns Promise resolving to access token or null if no valid tokens
157
+ * @returns Promise resolving to AuthCredential (wrapped access token) or null if no valid tokens
146
158
  * @throws OAuthFlowError if refresh fails
147
- */ export async function getValidAccessToken(tokenStore) {
159
+ */ export async function getValidOAuthAccessToken(tokenStore) {
148
160
  // Check if we have valid tokens
149
- if (tokenStore.hasValidTokens()) {
150
- return tokenStore.getAccessToken();
161
+ if (tokenStore.hasValidOauthToken()) {
162
+ const token = tokenStore.getCurrentOauthToken();
163
+ return token ? {
164
+ type: 'oauth',
165
+ token
166
+ } : null;
151
167
  }
152
168
  // Check if we have a refresh token
153
- const refreshToken = tokenStore.getRefreshToken();
169
+ const refreshToken = tokenStore.getCurrentRefreshToken();
154
170
  if (!refreshToken) {
155
171
  return null;
156
172
  }
157
- // Try to refresh
173
+ // Try to refresh (with one retry for transient auth errors)
158
174
  try {
159
175
  const tokens = await refreshAccessToken(refreshToken);
160
176
  tokenStore.setTokens(tokens);
161
- return tokens.accessToken;
177
+ return {
178
+ type: 'oauth',
179
+ token: tokens.accessToken
180
+ };
162
181
  } catch (error) {
163
- // Refresh failed - clear invalid tokens
164
- tokenStore.clearTokens();
182
+ const isAuthFailure = error instanceof TokenRefreshError && (error.statusCode === 401 || error.statusCode === 403 || error.statusCode === 400 && error.errorCode === 'invalid_grant');
183
+ if (isAuthFailure) {
184
+ // Retry once — a transient 401 (e.g. misconfigured proxy) shouldn't wipe tokens
185
+ try {
186
+ const tokens = await refreshAccessToken(refreshToken);
187
+ tokenStore.setTokens(tokens);
188
+ return {
189
+ type: 'oauth',
190
+ token: tokens.accessToken
191
+ };
192
+ } catch {
193
+ // Retry also failed — token is genuinely revoked
194
+ tokenStore.clearTokens();
195
+ }
196
+ }
165
197
  throw new OAuthFlowError('Failed to refresh access token', error instanceof Error ? error : undefined);
166
198
  }
167
199
  }
168
-
169
- //# sourceMappingURL=oauth-flow.js.map
200
+ /**
201
+ * Get a valid auth credential, checking process.env for plan access token
202
+ * first before checking tokenStore for OAuth tokens.
203
+ * *
204
+ * @param tokenStore - Token store to use for OAuth tokens
205
+ * @returns Promise resolving to AuthCredential or null
206
+ */ export async function getValidCredential(tokenStore) {
207
+ const envFigmaAccessToken = process.env.FIGMA_ACCESS_TOKEN;
208
+ if (envFigmaAccessToken) {
209
+ log.debug('Using FIGMA_ACCESS_TOKEN env var override; skipping stored OAuth tokens');
210
+ return {
211
+ type: 'plan_access_token',
212
+ token: envFigmaAccessToken
213
+ };
214
+ }
215
+ return getValidOAuthAccessToken(tokenStore);
216
+ }
217
+ /**
218
+ * Like getValidCredential but returns null instead of throwing on refresh failure.
219
+ * Use in commands that want to fall through to a login prompt on failure.
220
+ */ export async function tryGetCredential(tokenStore) {
221
+ try {
222
+ return await getValidCredential(tokenStore);
223
+ } catch {
224
+ return null;
225
+ }
226
+ }
227
+ /**
228
+ * Race the localhost callback listener against a pasted-code prompt.
229
+ *
230
+ * Used when no local browser was opened (remote/headless environments). Whichever
231
+ * settles first wins: if the listener receives the callback, the paste prompt is
232
+ * aborted; if the user pastes first, the listener is stopped. The listener's own
233
+ * timeout is non-fatal here — the user may take a while approving in the browser.
234
+ *
235
+ * @returns The authorization code from whichever source won
236
+ * @throws OAuthFlowError if the user cancels the paste prompt or the pasted value is invalid
237
+ */ async function waitForCallbackOrPastedCode({ callbackPromise, callbackServer, expectedState }) {
238
+ const abortController = new AbortController();
239
+ const listenerBranch = callbackPromise.then((result)=>{
240
+ // Listener won — tear down the paste prompt.
241
+ abortController.abort();
242
+ return result.code;
243
+ }, (error)=>{
244
+ // A timeout (or an unreachable listener on a remote box, which surfaces as a
245
+ // timeout) is non-fatal here — the user can still paste. Any other callback
246
+ // error means the browser actually reached the listener (denied consent, bad
247
+ // request, state mismatch), so surface it instead of hanging silently on the
248
+ // paste prompt.
249
+ if (error instanceof CallbackError && error.code === 'timeout') {
250
+ return new Promise(()=>{});
251
+ }
252
+ abortController.abort();
253
+ throw error;
254
+ });
255
+ const pasteBranch = (async ()=>{
256
+ // @clack/prompts TextOptions doesn't expose `signal` in its public type, but the
257
+ // underlying @clack/core PromptOptions does. Cast to reach the runtime capability.
258
+ const textOpts = {
259
+ message: 'Paste the redirect URL or code (optional):',
260
+ signal: abortController.signal,
261
+ validate: (value)=>validatePastedCode(value ?? '')
262
+ };
263
+ const pasted = await p.text(textOpts);
264
+ if (p.isCancel(pasted)) {
265
+ throw new OAuthFlowError('Authentication cancelled by user');
266
+ }
267
+ // Paste won — stop the listener before exchanging.
268
+ callbackServer.stop();
269
+ try {
270
+ return parsePastedCode(pasted, expectedState);
271
+ } catch (error) {
272
+ throw new OAuthFlowError(error instanceof Error ? error.message : 'Invalid pasted authorization code', error instanceof Error ? error : undefined);
273
+ }
274
+ })();
275
+ // Avoid an unhandled rejection when the paste prompt is aborted after the listener wins.
276
+ pasteBranch.catch(()=>{});
277
+ return Promise.race([
278
+ listenerBranch,
279
+ pasteBranch
280
+ ]);
281
+ }
282
+ function replaceRedirectUriPort(redirectUri, port) {
283
+ const url = new URL(redirectUri);
284
+ url.port = String(port);
285
+ return url.toString();
286
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Error parsing a pasted authorization code or redirect URL.
3
+ */
4
+ export declare class PastedCodeError extends Error {
5
+ constructor(message: string);
6
+ }
7
+ /**
8
+ * Parse a value the user pasted back after completing OAuth in their browser.
9
+ *
10
+ * Accepts either the full redirect URL (e.g.
11
+ * `http://localhost:34462/callback?code=...&state=...`) or a bare authorization
12
+ * code. When a URL is pasted, the `state` is validated against the value the CLI
13
+ * generated (CSRF protection); when a bare code is pasted, no state check is
14
+ * possible and PKCE alone gates the subsequent token exchange.
15
+ *
16
+ * @param input - Raw pasted text
17
+ * @param expectedState - The state value the CLI generated for this flow
18
+ * @returns The authorization code
19
+ * @throws PastedCodeError if the input is empty, is a URL without a code, or has a mismatched state
20
+ */
21
+ export declare function parsePastedCode(input: string, expectedState: string): string;
22
+ /**
23
+ * Structural validation for use as a `@clack/prompts` `text` validator.
24
+ *
25
+ * Returns `undefined` when the input could yield a code (so the prompt accepts it),
26
+ * or a human-readable message to re-prompt. Intentionally does NOT validate `state`
27
+ * — a state mismatch is a hard failure handled after the prompt resolves, not a
28
+ * re-prompt condition.
29
+ *
30
+ * @param input - Current prompt value
31
+ * @returns Error message string, or undefined if structurally valid
32
+ */
33
+ export declare function validatePastedCode(input: string): string | undefined;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Error parsing a pasted authorization code or redirect URL.
3
+ */ export class PastedCodeError extends Error {
4
+ constructor(message){
5
+ super(message);
6
+ this.name = 'PastedCodeError';
7
+ }
8
+ }
9
+ const NO_CODE_MESSAGE = 'That URL has no "code" parameter. Paste the full redirect URL or just the code.';
10
+ function parsePasteInput(input) {
11
+ const trimmed = input.trim();
12
+ if (!trimmed) {
13
+ return {
14
+ kind: 'empty'
15
+ };
16
+ }
17
+ let url;
18
+ try {
19
+ url = new URL(trimmed);
20
+ } catch {
21
+ return {
22
+ code: trimmed,
23
+ kind: 'bare-code'
24
+ };
25
+ }
26
+ const code = url.searchParams.get('code');
27
+ if (!code) {
28
+ return {
29
+ kind: 'url-missing-code'
30
+ };
31
+ }
32
+ return {
33
+ code,
34
+ kind: 'url',
35
+ state: url.searchParams.get('state')
36
+ };
37
+ }
38
+ /**
39
+ * Parse a value the user pasted back after completing OAuth in their browser.
40
+ *
41
+ * Accepts either the full redirect URL (e.g.
42
+ * `http://localhost:34462/callback?code=...&state=...`) or a bare authorization
43
+ * code. When a URL is pasted, the `state` is validated against the value the CLI
44
+ * generated (CSRF protection); when a bare code is pasted, no state check is
45
+ * possible and PKCE alone gates the subsequent token exchange.
46
+ *
47
+ * @param input - Raw pasted text
48
+ * @param expectedState - The state value the CLI generated for this flow
49
+ * @returns The authorization code
50
+ * @throws PastedCodeError if the input is empty, is a URL without a code, or has a mismatched state
51
+ */ export function parsePastedCode(input, expectedState) {
52
+ const parsed = parsePasteInput(input);
53
+ switch(parsed.kind){
54
+ case 'empty':
55
+ throw new PastedCodeError('No value provided.');
56
+ case 'bare-code':
57
+ return parsed.code;
58
+ case 'url-missing-code':
59
+ throw new PastedCodeError(NO_CODE_MESSAGE);
60
+ case 'url':
61
+ if (parsed.state !== null && parsed.state !== expectedState) {
62
+ throw new PastedCodeError('State mismatch — possible CSRF. Run login again.');
63
+ }
64
+ return parsed.code;
65
+ }
66
+ }
67
+ /**
68
+ * Structural validation for use as a `@clack/prompts` `text` validator.
69
+ *
70
+ * Returns `undefined` when the input could yield a code (so the prompt accepts it),
71
+ * or a human-readable message to re-prompt. Intentionally does NOT validate `state`
72
+ * — a state mismatch is a hard failure handled after the prompt resolves, not a
73
+ * re-prompt condition.
74
+ *
75
+ * @param input - Current prompt value
76
+ * @returns Error message string, or undefined if structurally valid
77
+ */ export function validatePastedCode(input) {
78
+ const parsed = parsePasteInput(input);
79
+ switch(parsed.kind){
80
+ case 'empty':
81
+ return 'Paste the redirect URL or the code.';
82
+ case 'url-missing-code':
83
+ return NO_CODE_MESSAGE;
84
+ default:
85
+ return undefined;
86
+ }
87
+ }
@@ -48,4 +48,3 @@ export declare function generateCodeChallenge(verifier: string): string;
48
48
  * // Include codeChallenge and codeChallengeMethod in authorization URL
49
49
  */
50
50
  export declare function generatePKCEPair(): PKCEPair;
51
- //# sourceMappingURL=pkce.d.ts.map
package/dist/auth/pkce.js CHANGED
@@ -67,5 +67,3 @@ import crypto from 'crypto';
67
67
  */ function base64UrlEncode(buffer) {
68
68
  return buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
69
69
  }
70
-
71
- //# sourceMappingURL=pkce.js.map
@@ -6,6 +6,7 @@
6
6
  * and have a shorter lifespan (15-30 minutes) than OAuth tokens.
7
7
  */
8
8
  import type { TokenStore } from './token-store.js';
9
+ import type { ProjectStoreScope } from './types.js';
9
10
  /**
10
11
  * Error during project token operations
11
12
  */
@@ -13,35 +14,49 @@ export declare class ProjectTokenError extends Error {
13
14
  cause?: Error | undefined;
14
15
  constructor(message: string, cause?: Error | undefined);
15
16
  }
17
+ /** Test-only: clears the in-memory token cache and any in-flight refresh promises. */
18
+ export declare function __resetProjectTokenCacheForTests(): void;
16
19
  /**
17
- * Get a valid project token for a tenant, refreshing if necessary
20
+ * Get a valid project token for a tenant, refreshing if necessary.
18
21
  *
19
- * This function:
20
- * 1. Checks if a stored project token exists and is valid (not expired)
21
- * 2. If expired or missing, gets a valid user access token
22
- * 3. Calls the Figma API to generate a new project token
23
- * 4. Stores the new project token in encrypted storage
24
- * 5. Returns the JWT string
22
+ * Lookup order:
23
+ * 1. Module-level in-memory cache (no I/O on hits).
24
+ * 2. In-flight refresh map concurrent callers with no cached entry share a single
25
+ * refresh promise, so the project-token endpoint is only hit once per cache key.
26
+ * 3. Persisted (`conf`-backed) token store picks up tokens minted by sibling processes.
27
+ * 4. Figma API — fetch + JWT validation, then write to both the persisted store and
28
+ * the in-memory cache.
25
29
  *
26
30
  * The project token is used by local Payload instances to authenticate
27
31
  * requests to the Content API without requiring a round-trip to Sinatra.
28
32
  *
29
- * @param tokenStore - Token store for persisting tokens
30
- * @param tenantId - The tenant/CMS ID to get a token for
33
+ * @param params.tokenStore - Token store for persisting tokens
34
+ * @param params.tenantId - Optional tenant/CMS ID; resolved from stored bootstrap data when omitted
35
+ * @param params.projectInfo - Optional project scope (defaults to env vars)
31
36
  * @returns Promise resolving to JWT token string or null if failed
32
37
  * @throws {ProjectTokenError} If token generation fails
33
38
  */
34
- export declare function getValidProjectToken(tokenStore: TokenStore, tenantId: string): Promise<null | string>;
39
+ export declare function getValidProjectToken({ projectInfo, tenantId, tokenStore, }: {
40
+ projectInfo?: ProjectStoreScope;
41
+ tenantId?: string;
42
+ tokenStore: TokenStore;
43
+ }): Promise<null | string>;
35
44
  /**
36
- * Refresh a project token for a tenant
45
+ * Force-refresh a project token, bypassing all cache layers.
37
46
  *
38
- * Forces a refresh of the project token even if the current one is still valid.
39
- * Useful for testing or when you want to ensure you have the freshest token.
47
+ * Invalidates the in-memory cache entry, the in-flight refresh promise (so a
48
+ * concurrently-running refresh that may already be returning a soon-to-be-stale
49
+ * token is dropped from the dedup map), and the persisted token store. Then
50
+ * delegates to {@link getValidProjectToken} to mint a fresh token.
40
51
  *
41
- * @param tokenStore - Token store for persisting tokens
42
- * @param tenantId - The tenant/CMS ID to refresh token for
52
+ * @param params.tokenStore - Token store for persisting tokens
53
+ * @param params.tenantId - Optional tenant/CMS ID; resolved from stored bootstrap data when omitted
54
+ * @param params.projectInfo - Optional project scope (defaults to env vars)
43
55
  * @returns Promise resolving to JWT token string or null if failed
44
56
  * @throws {ProjectTokenError} If token refresh fails
45
57
  */
46
- export declare function refreshProjectToken(tokenStore: TokenStore, tenantId: string): Promise<null | string>;
47
- //# sourceMappingURL=project-token.d.ts.map
58
+ export declare function refreshProjectToken(params: {
59
+ projectInfo?: ProjectStoreScope;
60
+ tenantId?: string;
61
+ tokenStore: TokenStore;
62
+ }): Promise<null | string>;