@payloadcms/figma 0.0.1-alpha.7 → 0.0.1-alpha.70

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 (390) hide show
  1. package/dist/api/control-plane.d.ts +56 -6
  2. package/dist/api/control-plane.js +181 -72
  3. package/dist/api/figma-api.d.ts +22 -1
  4. package/dist/api/figma-api.js +78 -25
  5. package/dist/auth/callback-server.d.ts +19 -7
  6. package/dist/auth/callback-server.js +72 -30
  7. package/dist/auth/credentials.d.ts +21 -0
  8. package/dist/auth/credentials.js +21 -0
  9. package/dist/auth/crypto-utils.d.ts +28 -0
  10. package/dist/auth/crypto-utils.js +132 -21
  11. package/dist/auth/jwt-validator.d.ts +2 -1
  12. package/dist/auth/jwt-validator.js +2 -2
  13. package/dist/auth/oauth-flow.d.ts +19 -3
  14. package/dist/auth/oauth-flow.js +77 -22
  15. package/dist/auth/project-token.d.ts +32 -16
  16. package/dist/auth/project-token.js +171 -65
  17. package/dist/auth/refresh.d.ts +2 -1
  18. package/dist/auth/refresh.js +25 -12
  19. package/dist/auth/token-store-migration.d.ts +58 -0
  20. package/dist/auth/token-store-migration.js +156 -0
  21. package/dist/auth/token-store.d.ts +63 -97
  22. package/dist/auth/token-store.js +405 -122
  23. package/dist/auth/types.d.ts +35 -4
  24. package/dist/cli.js +93 -6
  25. package/dist/commands/bootstrap.d.ts +18 -0
  26. package/dist/commands/bootstrap.js +90 -0
  27. package/dist/commands/build-lambda-zip.d.ts +5 -0
  28. package/dist/commands/build-lambda-zip.js +19 -0
  29. package/dist/commands/debug.d.ts +8 -0
  30. package/dist/commands/debug.js +180 -0
  31. package/dist/commands/deploy.d.ts +9 -0
  32. package/dist/commands/deploy.js +180 -151
  33. package/dist/commands/dump-tokens.d.ts +12 -0
  34. package/dist/commands/dump-tokens.js +69 -0
  35. package/dist/commands/env.d.ts +13 -0
  36. package/dist/commands/env.js +88 -0
  37. package/dist/commands/init.d.ts +9 -5
  38. package/dist/commands/init.js +241 -148
  39. package/dist/commands/list-tokens.d.ts +3 -3
  40. package/dist/commands/list-tokens.js +24 -9
  41. package/dist/commands/login.d.ts +8 -1
  42. package/dist/commands/login.js +34 -16
  43. package/dist/commands/logout.d.ts +5 -4
  44. package/dist/commands/logout.js +77 -15
  45. package/dist/commands/upgrade.d.ts +5 -0
  46. package/dist/commands/upgrade.js +331 -0
  47. package/dist/config/oauth.d.ts +17 -11
  48. package/dist/config/oauth.js +38 -37
  49. package/dist/constants.d.ts +63 -18
  50. package/dist/constants.js +158 -18
  51. package/dist/db-content-api/generated/content-api-types.d.ts +3978 -0
  52. package/dist/db-content-api/generated/content-api-types.js +7 -0
  53. package/dist/db-content-api/index.d.ts +37 -0
  54. package/dist/db-content-api/index.js +923 -0
  55. package/dist/db-content-api/temp-utilities/slug.d.ts +2 -0
  56. package/dist/db-content-api/temp-utilities/slug.js +3 -0
  57. package/dist/db-content-api/temp-utilities/sorting.d.ts +3 -0
  58. package/dist/db-content-api/temp-utilities/sorting.js +39 -0
  59. package/dist/db-content-api/temp-utilities/types.d.ts +22 -0
  60. package/dist/db-content-api/temp-utilities/types.js +15 -0
  61. package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts +39 -0
  62. package/dist/db-content-api/temp-utilities/unwrapDocument.js +64 -0
  63. package/dist/db-content-api/utilities/auth.d.ts +30 -0
  64. package/dist/db-content-api/utilities/auth.js +84 -0
  65. package/dist/db-content-api/utilities/data/applyDefaults.d.ts +7 -0
  66. package/dist/db-content-api/utilities/data/applyDefaults.js +75 -0
  67. package/dist/db-content-api/utilities/data/castFieldValue.d.ts +11 -0
  68. package/dist/db-content-api/utilities/data/castFieldValue.js +68 -0
  69. package/dist/db-content-api/utilities/data/index.d.ts +49 -0
  70. package/dist/db-content-api/utilities/data/index.js +301 -0
  71. package/dist/db-content-api/utilities/data/removeVirtualFields.d.ts +12 -0
  72. package/dist/db-content-api/utilities/data/removeVirtualFields.js +54 -0
  73. package/dist/db-content-api/utilities/data/stripFields.d.ts +48 -0
  74. package/dist/db-content-api/utilities/data/stripFields.js +195 -0
  75. package/dist/db-content-api/utilities/data/transformPublishedLocale.d.ts +23 -0
  76. package/dist/db-content-api/utilities/data/transformPublishedLocale.js +42 -0
  77. package/dist/db-content-api/utilities/data/validateRelationships.d.ts +7 -0
  78. package/dist/db-content-api/utilities/data/validateRelationships.js +102 -0
  79. package/dist/db-content-api/utilities/joins.d.ts +53 -0
  80. package/dist/db-content-api/utilities/joins.js +139 -0
  81. package/dist/db-content-api/utilities/locale/index.d.ts +10 -0
  82. package/dist/db-content-api/utilities/locale/index.js +21 -0
  83. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.d.ts +11 -0
  84. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js +74 -0
  85. package/dist/db-content-api/utilities/meta/buildMeta.d.ts +42 -0
  86. package/dist/db-content-api/utilities/meta/buildMeta.js +41 -0
  87. package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts +17 -0
  88. package/dist/db-content-api/utilities/meta/buildPathTypes.js +244 -0
  89. package/dist/db-content-api/utilities/meta/buildUniquePaths.d.ts +13 -0
  90. package/dist/db-content-api/utilities/meta/buildUniquePaths.js +62 -0
  91. package/dist/db-content-api/utilities/meta/normalizeLocaleInWhere.d.ts +10 -0
  92. package/dist/db-content-api/utilities/meta/normalizeLocaleInWhere.js +102 -0
  93. package/dist/db-content-api/utilities/where.d.ts +20 -0
  94. package/dist/db-content-api/utilities/where.js +108 -0
  95. package/dist/deploy/schedule-extract-plugin.d.ts +11 -0
  96. package/dist/deploy/schedule-extract-plugin.js +34 -0
  97. package/dist/endpoints/health.d.ts +3 -0
  98. package/dist/endpoints/health.js +11 -0
  99. package/dist/endpoints/schema.d.ts +3 -0
  100. package/dist/endpoints/schema.js +29 -0
  101. package/dist/exports/client.d.ts +3 -0
  102. package/dist/exports/client.js +3 -0
  103. package/dist/index.d.ts +2 -1
  104. package/dist/index.js +3 -1
  105. package/dist/lib/download-skill.d.ts +13 -0
  106. package/dist/lib/download-skill.js +79 -0
  107. package/dist/oauth/components/FigmaAvatar/index.d.ts +4 -0
  108. package/dist/oauth/components/FigmaAvatar/index.js +27 -0
  109. package/dist/oauth/components/FigmaAvatar/index.scss +12 -0
  110. package/dist/oauth/components/FigmaAvatarCell/index.d.ts +5 -0
  111. package/dist/oauth/components/FigmaAvatarCell/index.js +25 -0
  112. package/dist/oauth/components/FigmaAvatarCell/index.scss +5 -0
  113. package/dist/oauth/components/FigmaAvatarPlaceholder/index.d.ts +9 -0
  114. package/dist/oauth/components/FigmaAvatarPlaceholder/index.js +37 -0
  115. package/dist/oauth/components/FigmaAvatarPlaceholder/index.scss +28 -0
  116. package/dist/oauth/components/LoginButton/iframeAutoLogin.d.ts +82 -0
  117. package/dist/oauth/components/LoginButton/iframeAutoLogin.js +170 -0
  118. package/dist/oauth/components/LoginButton/index.js +144 -11
  119. package/dist/oauth/components/LoginButton/index.scss +75 -3
  120. package/dist/oauth/components/LogoutButton/index.js +19 -6
  121. package/dist/oauth/defaults.d.ts +3 -1
  122. package/dist/oauth/defaults.js +68 -10
  123. package/dist/oauth/endpoints/getLoginEndpoint.js +72 -77
  124. package/dist/oauth/endpoints/getLogoutEndpoint.js +7 -4
  125. package/dist/oauth/endpoints/getMetaEndpoint.js +18 -3
  126. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js +11 -2
  127. package/dist/oauth/index.js +27 -5
  128. package/dist/oauth/strategy/index.d.ts +0 -2
  129. package/dist/oauth/strategy/index.js +40 -17
  130. package/dist/oauth/types.d.ts +23 -6
  131. package/dist/oauth/utilities/establishSession.d.ts +23 -0
  132. package/dist/oauth/utilities/establishSession.js +82 -0
  133. package/dist/oauth/utilities/exchangeCodeForAccessToken.d.ts +24 -0
  134. package/dist/oauth/utilities/exchangeCodeForAccessToken.js +28 -0
  135. package/dist/oauth/utilities/figmaHostnames.d.ts +3 -0
  136. package/dist/oauth/utilities/figmaHostnames.js +26 -0
  137. package/dist/oauth/utilities/getAuthorizeURL.d.ts +65 -1
  138. package/dist/oauth/utilities/getAuthorizeURL.js +57 -2
  139. package/dist/oauth/utilities/isAbsoluteURL.d.ts +2 -0
  140. package/dist/oauth/utilities/isAbsoluteURL.js +3 -0
  141. package/dist/oauth/utilities/isDuplicateKeyError.d.ts +7 -0
  142. package/dist/oauth/utilities/isDuplicateKeyError.js +14 -0
  143. package/dist/oauth/utilities/refreshTokens.js +6 -3
  144. package/dist/plugin/auth-preflight.d.ts +8 -0
  145. package/dist/plugin/auth-preflight.js +20 -0
  146. package/dist/plugin/bootstrap-preflight.d.ts +23 -0
  147. package/dist/plugin/bootstrap-preflight.js +45 -0
  148. package/dist/plugin/build-config.d.ts +27 -15
  149. package/dist/plugin/build-config.js +327 -17
  150. package/dist/plugin/dev-cookie-names.d.ts +14 -0
  151. package/dist/plugin/dev-cookie-names.js +19 -0
  152. package/dist/storage-content-api/api-types.d.ts +168 -0
  153. package/dist/storage-content-api/api-types.js +6 -0
  154. package/dist/storage-content-api/client-uploads/ClientUploadHandler.d.ts +9 -0
  155. package/dist/storage-content-api/client-uploads/ClientUploadHandler.js +43 -0
  156. package/dist/storage-content-api/client-uploads/generateSignedURL.d.ts +13 -0
  157. package/dist/storage-content-api/client-uploads/generateSignedURL.js +39 -0
  158. package/dist/storage-content-api/client.d.ts +6 -0
  159. package/dist/storage-content-api/client.js +39 -0
  160. package/dist/storage-content-api/generateURL.d.ts +7 -0
  161. package/dist/storage-content-api/generateURL.js +8 -0
  162. package/dist/storage-content-api/handleDelete.d.ts +8 -0
  163. package/dist/storage-content-api/handleDelete.js +17 -0
  164. package/dist/storage-content-api/handleUpload.d.ts +11 -0
  165. package/dist/storage-content-api/handleUpload.js +144 -0
  166. package/dist/storage-content-api/index.d.ts +5 -0
  167. package/dist/storage-content-api/index.js +31 -0
  168. package/dist/storage-content-api/staticHandler.d.ts +10 -0
  169. package/dist/storage-content-api/staticHandler.js +63 -0
  170. package/dist/storage-content-api/types.d.ts +10 -0
  171. package/dist/storage-content-api/types.js +3 -0
  172. package/dist/storage-content-api/utilities/getSafeFilename.d.ts +12 -0
  173. package/dist/storage-content-api/utilities/getSafeFilename.js +61 -0
  174. package/dist/storage-content-api/utilities/index.d.ts +3 -0
  175. package/dist/storage-content-api/utilities/index.js +4 -0
  176. package/dist/storage-content-api/utilities/parseClientUploadContext.d.ts +19 -0
  177. package/dist/storage-content-api/utilities/parseClientUploadContext.js +30 -0
  178. package/dist/templates/.env.example +5 -0
  179. package/dist/templates/README.md +19 -0
  180. package/dist/types/config.d.ts +2 -1
  181. package/dist/types/config.js +0 -2
  182. package/dist/types.d.ts +10 -1
  183. package/dist/utils/adapters/nextjs.d.ts +9 -0
  184. package/dist/utils/adapters/nextjs.js +64 -0
  185. package/dist/utils/adapters/nitro.d.ts +9 -0
  186. package/dist/utils/adapters/nitro.js +169 -0
  187. package/dist/utils/adapters/vite.d.ts +10 -0
  188. package/dist/utils/adapters/vite.js +33 -0
  189. package/dist/utils/asset-collection.d.ts +27 -6
  190. package/dist/utils/asset-collection.js +59 -30
  191. package/dist/utils/build-detection.d.ts +5 -11
  192. package/dist/utils/build-detection.js +74 -11
  193. package/dist/utils/build-lambda-zip.d.ts +16 -0
  194. package/dist/utils/build-lambda-zip.js +78 -0
  195. package/dist/utils/cache-bootstrap.d.ts +8 -0
  196. package/dist/utils/cache-bootstrap.js +18 -0
  197. package/dist/utils/config.js +1 -1
  198. package/dist/utils/deploy-adapter.d.ts +40 -0
  199. package/dist/utils/deploy-adapter.js +58 -0
  200. package/dist/utils/download-template.d.ts +9 -1
  201. package/dist/utils/download-template.js +24 -18
  202. package/dist/utils/env-management.d.ts +24 -7
  203. package/dist/utils/env-management.js +119 -64
  204. package/dist/utils/format-env-suffix.d.ts +12 -0
  205. package/dist/utils/format-env-suffix.js +13 -0
  206. package/dist/utils/formatter.js +23 -11
  207. package/dist/utils/fs-utils.d.ts +6 -0
  208. package/dist/utils/fs-utils.js +27 -0
  209. package/dist/utils/handle-upgrade.d.ts +9 -0
  210. package/dist/utils/handle-upgrade.js +41 -0
  211. package/dist/utils/lambda-config.d.ts +3 -1
  212. package/dist/utils/lambda-config.js +75 -78
  213. package/dist/utils/messages.d.ts +1 -2
  214. package/dist/utils/messages.js +39 -11
  215. package/dist/utils/package-manager.d.ts +24 -0
  216. package/dist/utils/package-manager.js +53 -0
  217. package/dist/utils/parse-template-spec.d.ts +12 -0
  218. package/dist/utils/parse-template-spec.js +62 -0
  219. package/dist/utils/payload-config-ast.d.ts +27 -6
  220. package/dist/utils/payload-config-ast.js +106 -58
  221. package/dist/utils/payload-config-finder.d.ts +2 -2
  222. package/dist/utils/payload-config-finder.js +48 -9
  223. package/dist/utils/payload-config-modifier.d.ts +1 -1
  224. package/dist/utils/payload-config-modifier.js +114 -66
  225. package/dist/utils/payload-package-check.d.ts +33 -2
  226. package/dist/utils/payload-package-check.js +129 -28
  227. package/dist/utils/project.d.ts +7 -2
  228. package/dist/utils/project.js +60 -32
  229. package/dist/utils/resolve-environment.d.ts +14 -0
  230. package/dist/utils/resolve-environment.js +31 -0
  231. package/dist/utils/s3-upload.d.ts +7 -2
  232. package/dist/utils/s3-upload.js +39 -6
  233. package/dist/utils/token-display.d.ts +5 -1
  234. package/dist/utils/token-display.js +49 -22
  235. package/dist/utils/typescript-validator.js +4 -6
  236. package/dist/utils/version-check.d.ts +3 -0
  237. package/dist/utils/version-check.js +38 -0
  238. package/package.json +44 -15
  239. package/dist/api/control-plane.d.ts.map +0 -1
  240. package/dist/api/control-plane.js.map +0 -1
  241. package/dist/api/figma-api.d.ts.map +0 -1
  242. package/dist/api/figma-api.js.map +0 -1
  243. package/dist/auth/browser.d.ts.map +0 -1
  244. package/dist/auth/browser.js.map +0 -1
  245. package/dist/auth/callback-server.d.ts.map +0 -1
  246. package/dist/auth/callback-server.js.map +0 -1
  247. package/dist/auth/crypto-utils.d.ts.map +0 -1
  248. package/dist/auth/crypto-utils.js.map +0 -1
  249. package/dist/auth/jwt-validator.d.ts.map +0 -1
  250. package/dist/auth/jwt-validator.js.map +0 -1
  251. package/dist/auth/oauth-flow.d.ts.map +0 -1
  252. package/dist/auth/oauth-flow.js.map +0 -1
  253. package/dist/auth/pkce.d.ts.map +0 -1
  254. package/dist/auth/pkce.js.map +0 -1
  255. package/dist/auth/project-token.d.ts.map +0 -1
  256. package/dist/auth/project-token.js.map +0 -1
  257. package/dist/auth/refresh.d.ts.map +0 -1
  258. package/dist/auth/refresh.js.map +0 -1
  259. package/dist/auth/token-store.d.ts.map +0 -1
  260. package/dist/auth/token-store.js.map +0 -1
  261. package/dist/auth/types.d.ts.map +0 -1
  262. package/dist/auth/types.js.map +0 -1
  263. package/dist/cli.d.ts.map +0 -1
  264. package/dist/cli.js.map +0 -1
  265. package/dist/commands/deploy.d.ts.map +0 -1
  266. package/dist/commands/deploy.js.map +0 -1
  267. package/dist/commands/init.d.ts.map +0 -1
  268. package/dist/commands/init.js.map +0 -1
  269. package/dist/commands/list-tokens.d.ts.map +0 -1
  270. package/dist/commands/list-tokens.js.map +0 -1
  271. package/dist/commands/login.d.ts.map +0 -1
  272. package/dist/commands/login.js.map +0 -1
  273. package/dist/commands/logout.d.ts.map +0 -1
  274. package/dist/commands/logout.js.map +0 -1
  275. package/dist/config/oauth.d.ts.map +0 -1
  276. package/dist/config/oauth.js.map +0 -1
  277. package/dist/constants.d.ts.map +0 -1
  278. package/dist/constants.js.map +0 -1
  279. package/dist/exports/client.d.ts.map +0 -1
  280. package/dist/exports/client.js.map +0 -1
  281. package/dist/index.d.ts.map +0 -1
  282. package/dist/index.js.map +0 -1
  283. package/dist/oauth/components/LoginButton/index.d.ts.map +0 -1
  284. package/dist/oauth/components/LoginButton/index.js.map +0 -1
  285. package/dist/oauth/components/LogoutButton/index.d.ts.map +0 -1
  286. package/dist/oauth/components/LogoutButton/index.js.map +0 -1
  287. package/dist/oauth/defaults.d.ts.map +0 -1
  288. package/dist/oauth/defaults.js.map +0 -1
  289. package/dist/oauth/endpoints/getLoginEndpoint.d.ts.map +0 -1
  290. package/dist/oauth/endpoints/getLoginEndpoint.js.map +0 -1
  291. package/dist/oauth/endpoints/getLogoutEndpoint.d.ts.map +0 -1
  292. package/dist/oauth/endpoints/getLogoutEndpoint.js.map +0 -1
  293. package/dist/oauth/endpoints/getMetaEndpoint.d.ts.map +0 -1
  294. package/dist/oauth/endpoints/getMetaEndpoint.js.map +0 -1
  295. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.d.ts.map +0 -1
  296. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js.map +0 -1
  297. package/dist/oauth/exports/client.d.ts.map +0 -1
  298. package/dist/oauth/exports/client.js.map +0 -1
  299. package/dist/oauth/hooks/afterLogout.d.ts.map +0 -1
  300. package/dist/oauth/hooks/afterLogout.js.map +0 -1
  301. package/dist/oauth/hooks/me.d.ts.map +0 -1
  302. package/dist/oauth/hooks/me.js.map +0 -1
  303. package/dist/oauth/hooks/refresh.d.ts.map +0 -1
  304. package/dist/oauth/hooks/refresh.js.map +0 -1
  305. package/dist/oauth/index.d.ts.map +0 -1
  306. package/dist/oauth/index.js.map +0 -1
  307. package/dist/oauth/strategy/index.d.ts.map +0 -1
  308. package/dist/oauth/strategy/index.js.map +0 -1
  309. package/dist/oauth/types.d.ts.map +0 -1
  310. package/dist/oauth/types.js.map +0 -1
  311. package/dist/oauth/utilities/clearCookie.d.ts.map +0 -1
  312. package/dist/oauth/utilities/clearCookie.js.map +0 -1
  313. package/dist/oauth/utilities/createCookieOptions.d.ts.map +0 -1
  314. package/dist/oauth/utilities/createCookieOptions.js.map +0 -1
  315. package/dist/oauth/utilities/createDebugLogger.d.ts.map +0 -1
  316. package/dist/oauth/utilities/createDebugLogger.js.map +0 -1
  317. package/dist/oauth/utilities/extractOrigin.d.ts.map +0 -1
  318. package/dist/oauth/utilities/extractOrigin.js.map +0 -1
  319. package/dist/oauth/utilities/getAdminCollectionSlug.d.ts.map +0 -1
  320. package/dist/oauth/utilities/getAdminCollectionSlug.js.map +0 -1
  321. package/dist/oauth/utilities/getAdminPath.d.ts +0 -8
  322. package/dist/oauth/utilities/getAdminPath.d.ts.map +0 -1
  323. package/dist/oauth/utilities/getAdminPath.js +0 -9
  324. package/dist/oauth/utilities/getAdminPath.js.map +0 -1
  325. package/dist/oauth/utilities/getAuthorizeURL.d.ts.map +0 -1
  326. package/dist/oauth/utilities/getAuthorizeURL.js.map +0 -1
  327. package/dist/oauth/utilities/getCookieExpiration.d.ts.map +0 -1
  328. package/dist/oauth/utilities/getCookieExpiration.js.map +0 -1
  329. package/dist/oauth/utilities/getSecondsFromTokenExp.d.ts.map +0 -1
  330. package/dist/oauth/utilities/getSecondsFromTokenExp.js.map +0 -1
  331. package/dist/oauth/utilities/getTokenExp.d.ts.map +0 -1
  332. package/dist/oauth/utilities/getTokenExp.js.map +0 -1
  333. package/dist/oauth/utilities/getUsernameField.d.ts.map +0 -1
  334. package/dist/oauth/utilities/getUsernameField.js.map +0 -1
  335. package/dist/oauth/utilities/hasUserTokenPropsChanged.d.ts.map +0 -1
  336. package/dist/oauth/utilities/hasUserTokenPropsChanged.js.map +0 -1
  337. package/dist/oauth/utilities/mergeHeaders.d.ts.map +0 -1
  338. package/dist/oauth/utilities/mergeHeaders.js.map +0 -1
  339. package/dist/oauth/utilities/refreshTokens.d.ts.map +0 -1
  340. package/dist/oauth/utilities/refreshTokens.js.map +0 -1
  341. package/dist/plugin/adapter.d.ts.map +0 -1
  342. package/dist/plugin/adapter.js.map +0 -1
  343. package/dist/plugin/build-config.d.ts.map +0 -1
  344. package/dist/plugin/build-config.js.map +0 -1
  345. package/dist/types/config.d.ts.map +0 -1
  346. package/dist/types/config.js.map +0 -1
  347. package/dist/types.d.ts.map +0 -1
  348. package/dist/types.js.map +0 -1
  349. package/dist/utils/asset-collection.d.ts.map +0 -1
  350. package/dist/utils/asset-collection.js.map +0 -1
  351. package/dist/utils/build-detection.d.ts.map +0 -1
  352. package/dist/utils/build-detection.js.map +0 -1
  353. package/dist/utils/config.d.ts.map +0 -1
  354. package/dist/utils/config.js.map +0 -1
  355. package/dist/utils/download-template.d.ts.map +0 -1
  356. package/dist/utils/download-template.js.map +0 -1
  357. package/dist/utils/env-management.d.ts.map +0 -1
  358. package/dist/utils/env-management.js.map +0 -1
  359. package/dist/utils/format.d.ts.map +0 -1
  360. package/dist/utils/format.js.map +0 -1
  361. package/dist/utils/formatter.d.ts.map +0 -1
  362. package/dist/utils/formatter.js.map +0 -1
  363. package/dist/utils/git.d.ts.map +0 -1
  364. package/dist/utils/git.js.map +0 -1
  365. package/dist/utils/is-debug.d.ts.map +0 -1
  366. package/dist/utils/is-debug.js.map +0 -1
  367. package/dist/utils/lambda-config.d.ts.map +0 -1
  368. package/dist/utils/lambda-config.js.map +0 -1
  369. package/dist/utils/log.d.ts.map +0 -1
  370. package/dist/utils/log.js.map +0 -1
  371. package/dist/utils/messages.d.ts.map +0 -1
  372. package/dist/utils/messages.js.map +0 -1
  373. package/dist/utils/package-manager.d.ts.map +0 -1
  374. package/dist/utils/package-manager.js.map +0 -1
  375. package/dist/utils/payload-config-ast.d.ts.map +0 -1
  376. package/dist/utils/payload-config-ast.js.map +0 -1
  377. package/dist/utils/payload-config-finder.d.ts.map +0 -1
  378. package/dist/utils/payload-config-finder.js.map +0 -1
  379. package/dist/utils/payload-config-modifier.d.ts.map +0 -1
  380. package/dist/utils/payload-config-modifier.js.map +0 -1
  381. package/dist/utils/payload-package-check.d.ts.map +0 -1
  382. package/dist/utils/payload-package-check.js.map +0 -1
  383. package/dist/utils/project.d.ts.map +0 -1
  384. package/dist/utils/project.js.map +0 -1
  385. package/dist/utils/s3-upload.d.ts.map +0 -1
  386. package/dist/utils/s3-upload.js.map +0 -1
  387. package/dist/utils/token-display.d.ts.map +0 -1
  388. package/dist/utils/token-display.js.map +0 -1
  389. package/dist/utils/typescript-validator.d.ts.map +0 -1
  390. package/dist/utils/typescript-validator.js.map +0 -1
@@ -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,21 @@ 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>;
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>;
62
78
  //# sourceMappingURL=oauth-flow.d.ts.map
@@ -1,11 +1,11 @@
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
6
  import { CallbackServer } from './callback-server.js';
7
7
  import { generatePKCEPair } from './pkce.js';
8
- import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
8
+ import { exchangeCodeForTokens, refreshAccessToken, TokenRefreshError } from './refresh.js';
9
9
  /**
10
10
  * Error during OAuth flow
11
11
  */ export class OAuthFlowError extends Error {
@@ -32,16 +32,17 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
32
32
  * @throws OAuthFlowError if any step fails
33
33
  */ export async function executeOAuthFlow(tokenStore, options = {}) {
34
34
  // 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';
35
+ // Default to false for OAuth
36
+ const shouldMock = process.env.FIGMA_MOCK_OAUTH === 'true';
37
+ const oauthConfig = getOAuthConfig();
37
38
  if (shouldMock) {
38
39
  // MOCK IMPLEMENTATION: Return mock tokens for testing
39
- log.debug('Using mock OAuth flow (FIGMA_MOCK_OAUTH != "false")');
40
+ log.debug('Using mock OAuth flow (FIGMA_MOCK_OAUTH = true)');
40
41
  const mockTokens = {
41
42
  accessToken: 'figt_mock_access_token_' + crypto.randomBytes(16).toString('hex'),
42
43
  expiresAt: Date.now() + 2 * 60 * 60 * 1000,
43
44
  refreshToken: 'figt_mock_refresh_token_' + crypto.randomBytes(16).toString('hex'),
44
- scopes: options.scopes || OAUTH_CONFIG.scopes,
45
+ scopes: options.scopes || oauthConfig.scopes,
45
46
  tokenType: 'Bearer'
46
47
  };
47
48
  // Store mock tokens
@@ -52,28 +53,30 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
52
53
  };
53
54
  }
54
55
  // REAL OAUTH IMPLEMENTATION
55
- const { clientId = OAUTH_CONFIG.clientId, port = 3000, redirectUri = OAUTH_CONFIG.redirectUri, scopes = OAUTH_CONFIG.scopes, timeoutMs = 120000 } = options;
56
+ const { clientId = oauthConfig.clientId, fallbackPorts, port, redirectUri = oauthConfig.redirectUri, scopes = oauthConfig.scopes, timeoutMs = 120000 } = options;
56
57
  // Generate PKCE pair for enhanced security
57
58
  const { codeChallenge, codeChallengeMethod, codeVerifier } = generatePKCEPair();
58
59
  // Generate random state for CSRF protection
59
60
  const state = crypto.randomBytes(32).toString('base64url');
60
61
  // Create callback server
61
62
  const callbackServer = new CallbackServer({
63
+ fallbackPorts,
62
64
  port,
63
65
  timeoutMs
64
66
  });
65
67
  try {
66
68
  // Start waiting for callback (this starts the server and captures actual port)
67
69
  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));
70
+ callbackPromise.catch(()=>{
71
+ // The callback promise is awaited below; avoid an unhandled rejection if startup fails early.
72
+ });
70
73
  // Get the actual port (may differ from preferred if that was in use)
71
- const actualPort = callbackServer.getActualPort();
74
+ const actualPort = await callbackServer.waitUntilReady();
72
75
  // Build redirect URI with actual port
73
- const actualRedirectUri = redirectUri.replace(/:\d+/, `:${actualPort}`);
76
+ const actualRedirectUri = replaceRedirectUriPort(redirectUri, actualPort);
74
77
  // Build authorization URL
75
78
  const authUrl = buildAuthorizationUrl({
76
- authorizationUrl: OAUTH_CONFIG.authorizationUrl,
79
+ authorizationUrl: oauthConfig.authorizationUrl,
77
80
  clientId,
78
81
  codeChallenge,
79
82
  codeChallengeMethod,
@@ -84,7 +87,7 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
84
87
  // Prompt user to open browser
85
88
  const shouldOpenBrowser = await p.confirm({
86
89
  initialValue: true,
87
- message: 'Log in or create Figma account in your browser?'
90
+ message: 'Authenticate with Figma in your browser?'
88
91
  });
89
92
  if (p.isCancel(shouldOpenBrowser)) {
90
93
  throw new OAuthFlowError('Authentication cancelled by user');
@@ -142,28 +145,80 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
142
145
  * refreshes using the refresh token. If no tokens exist, returns null.
143
146
  *
144
147
  * @param tokenStore - Token store to use
145
- * @returns Promise resolving to access token or null if no valid tokens
148
+ * @returns Promise resolving to AuthCredential (wrapped access token) or null if no valid tokens
146
149
  * @throws OAuthFlowError if refresh fails
147
- */ export async function getValidAccessToken(tokenStore) {
150
+ */ export async function getValidOAuthAccessToken(tokenStore) {
148
151
  // Check if we have valid tokens
149
- if (tokenStore.hasValidTokens()) {
150
- return tokenStore.getAccessToken();
152
+ if (tokenStore.hasValidOauthToken()) {
153
+ const token = tokenStore.getCurrentOauthToken();
154
+ return token ? {
155
+ type: 'oauth',
156
+ token
157
+ } : null;
151
158
  }
152
159
  // Check if we have a refresh token
153
- const refreshToken = tokenStore.getRefreshToken();
160
+ const refreshToken = tokenStore.getCurrentRefreshToken();
154
161
  if (!refreshToken) {
155
162
  return null;
156
163
  }
157
- // Try to refresh
164
+ // Try to refresh (with one retry for transient auth errors)
158
165
  try {
159
166
  const tokens = await refreshAccessToken(refreshToken);
160
167
  tokenStore.setTokens(tokens);
161
- return tokens.accessToken;
168
+ return {
169
+ type: 'oauth',
170
+ token: tokens.accessToken
171
+ };
162
172
  } catch (error) {
163
- // Refresh failed - clear invalid tokens
164
- tokenStore.clearTokens();
173
+ const isAuthFailure = error instanceof TokenRefreshError && (error.statusCode === 401 || error.statusCode === 403 || error.statusCode === 400 && error.errorCode === 'invalid_grant');
174
+ if (isAuthFailure) {
175
+ // Retry once — a transient 401 (e.g. misconfigured proxy) shouldn't wipe tokens
176
+ try {
177
+ const tokens = await refreshAccessToken(refreshToken);
178
+ tokenStore.setTokens(tokens);
179
+ return {
180
+ type: 'oauth',
181
+ token: tokens.accessToken
182
+ };
183
+ } catch {
184
+ // Retry also failed — token is genuinely revoked
185
+ tokenStore.clearTokens();
186
+ }
187
+ }
165
188
  throw new OAuthFlowError('Failed to refresh access token', error instanceof Error ? error : undefined);
166
189
  }
167
190
  }
191
+ /**
192
+ * Get a valid auth credential, checking process.env for plan access token
193
+ * first before checking tokenStore for OAuth tokens.
194
+ * *
195
+ * @param tokenStore - Token store to use for OAuth tokens
196
+ * @returns Promise resolving to AuthCredential or null
197
+ */ export async function getValidCredential(tokenStore) {
198
+ const envFigmaAccessToken = process.env.FIGMA_ACCESS_TOKEN;
199
+ if (envFigmaAccessToken) {
200
+ log.debug('Using FIGMA_ACCESS_TOKEN env var override; skipping stored OAuth tokens');
201
+ return {
202
+ type: 'plan_access_token',
203
+ token: envFigmaAccessToken
204
+ };
205
+ }
206
+ return getValidOAuthAccessToken(tokenStore);
207
+ }
208
+ /**
209
+ * Like getValidCredential but returns null instead of throwing on refresh failure.
210
+ * Use in commands that want to fall through to a login prompt on failure.
211
+ */ export async function tryGetCredential(tokenStore) {
212
+ try {
213
+ return await getValidCredential(tokenStore);
214
+ } catch {
215
+ return null;
216
+ }
217
+ }
218
+ function replaceRedirectUriPort(redirectUri, port) {
219
+ const url = new URL(redirectUri);
220
+ url.port = String(port);
221
+ return url.toString();
222
+ }
168
223
 
169
224
  //# sourceMappingURL=oauth-flow.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,50 @@ 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>;
58
+ export declare function refreshProjectToken(params: {
59
+ projectInfo?: ProjectStoreScope;
60
+ tenantId?: string;
61
+ tokenStore: TokenStore;
62
+ }): Promise<null | string>;
47
63
  //# sourceMappingURL=project-token.d.ts.map
@@ -5,10 +5,11 @@
5
5
  * to the Content API. Project tokens are scoped to a specific tenant/CMS
6
6
  * and have a shorter lifespan (15-30 minutes) than OAuth tokens.
7
7
  */ import { getProjectToken as fetchProjectToken } from '../api/figma-api.js';
8
- import { getEnvironment } from '../constants.js';
8
+ import { PROJECT_TOKEN_EXPIRY_BUFFER_SECONDS } from '../config/oauth.js';
9
+ import { getInfraEnvironment } from '../constants.js';
9
10
  import * as log from '../utils/log.js';
10
11
  import { JWTValidationError, validateProjectToken } from './jwt-validator.js';
11
- import { getValidAccessToken } from './oauth-flow.js';
12
+ import { getValidCredential } from './oauth-flow.js';
12
13
  /**
13
14
  * Error during project token operations
14
15
  */ export class ProjectTokenError extends Error {
@@ -18,6 +19,21 @@ import { getValidAccessToken } from './oauth-flow.js';
18
19
  this.name = 'ProjectTokenError';
19
20
  }
20
21
  }
22
+ const projectTokenCache = new Map();
23
+ const inFlightRefreshes = new Map();
24
+ function buildCacheKey(params) {
25
+ const projectId = params.projectInfo?.projectId ?? '';
26
+ const environmentName = params.projectInfo?.environmentName ?? '';
27
+ return `${params.tenantId}::${projectId}::${environmentName}`;
28
+ }
29
+ function isCachedTokenValid(entry) {
30
+ const bufferMs = PROJECT_TOKEN_EXPIRY_BUFFER_SECONDS * 1000;
31
+ return Date.now() < entry.expiresAt - bufferMs;
32
+ }
33
+ /** Test-only: clears the in-memory token cache and any in-flight refresh promises. */ export function __resetProjectTokenCacheForTests() {
34
+ projectTokenCache.clear();
35
+ inFlightRefreshes.clear();
36
+ }
21
37
  /**
22
38
  * Parse JWT claims from token without validation
23
39
  * Used for mock tokens where signature validation is not needed
@@ -43,89 +59,179 @@ import { getValidAccessToken } from './oauth-flow.js';
43
59
  }
44
60
  }
45
61
  /**
46
- * Get a valid project token for a tenant, refreshing if necessary
62
+ * Get a valid project token for a tenant, refreshing if necessary.
47
63
  *
48
- * This function:
49
- * 1. Checks if a stored project token exists and is valid (not expired)
50
- * 2. If expired or missing, gets a valid user access token
51
- * 3. Calls the Figma API to generate a new project token
52
- * 4. Stores the new project token in encrypted storage
53
- * 5. Returns the JWT string
64
+ * Lookup order:
65
+ * 1. Module-level in-memory cache (no I/O on hits).
66
+ * 2. In-flight refresh map concurrent callers with no cached entry share a single
67
+ * refresh promise, so the project-token endpoint is only hit once per cache key.
68
+ * 3. Persisted (`conf`-backed) token store picks up tokens minted by sibling processes.
69
+ * 4. Figma API — fetch + JWT validation, then write to both the persisted store and
70
+ * the in-memory cache.
54
71
  *
55
72
  * The project token is used by local Payload instances to authenticate
56
73
  * requests to the Content API without requiring a round-trip to Sinatra.
57
74
  *
58
- * @param tokenStore - Token store for persisting tokens
59
- * @param tenantId - The tenant/CMS ID to get a token for
75
+ * @param params.tokenStore - Token store for persisting tokens
76
+ * @param params.tenantId - Optional tenant/CMS ID; resolved from stored bootstrap data when omitted
77
+ * @param params.projectInfo - Optional project scope (defaults to env vars)
60
78
  * @returns Promise resolving to JWT token string or null if failed
61
79
  * @throws {ProjectTokenError} If token generation fails
62
- */ export async function getValidProjectToken(tokenStore, tenantId) {
63
- // Check if we have a valid project token already
64
- if (tokenStore.hasValidProjectToken(tenantId)) {
65
- const projectToken = tokenStore.getProjectToken(tenantId);
66
- return projectToken?.token || null;
80
+ */ export async function getValidProjectToken({ projectInfo, tenantId, tokenStore }) {
81
+ if (process.env.FIGMA_CONTENT_API_ACCESS_KEY) {
82
+ log.debug('FIGMA_CONTENT_API_ACCESS_KEY is set; skipping project token retrieval from API');
83
+ return null;
67
84
  }
68
- // We need to refresh the project token
69
- // First, get a valid user access token (will auto-refresh if needed)
70
- let accessToken;
71
- try {
72
- accessToken = await getValidAccessToken(tokenStore);
73
- } catch (error) {
74
- throw new ProjectTokenError('Failed to get valid access token for project token refresh', error instanceof Error ? error : undefined);
85
+ const resolvedTenantId = tenantId ?? tokenStore.getTenantId({
86
+ projectInfo
87
+ });
88
+ if (!resolvedTenantId) {
89
+ throw new ProjectTokenError('tenantId was not provided and could not be resolved from bootstrap data');
75
90
  }
76
- if (!accessToken) {
77
- // No valid user tokens available - user needs to authenticate
78
- return null;
91
+ const cacheKey = buildCacheKey({
92
+ projectInfo,
93
+ tenantId: resolvedTenantId
94
+ });
95
+ const cached = projectTokenCache.get(cacheKey);
96
+ if (cached && isCachedTokenValid(cached)) {
97
+ return cached.token;
79
98
  }
80
- // Fetch a new project token from the Figma API
81
- const projectToken = await fetchProjectToken(accessToken, tenantId);
82
- // Validate the JWT signature and claims (skip for mocks)
83
- const shouldMock = process.env.FIGMA_MOCK_PROJECT_TOKEN !== 'false';
84
- let validatedClaims;
85
- if (shouldMock) {
86
- // MOCK: Skip JWT validation and parse claims directly
87
- log.debug('Skipping JWT validation for mock project token');
88
- validatedClaims = parseJWTClaims(projectToken.token);
89
- } else {
90
- // REAL: Validate JWT signature against JWKS
99
+ const inFlight = inFlightRefreshes.get(cacheKey);
100
+ if (inFlight) {
101
+ return inFlight;
102
+ }
103
+ // The IIFE references this holder so it can check whether it is still the
104
+ // active refresh before writing back to the caches. Without this guard a
105
+ // stale in-flight refresh could clobber a fresh token written by a later
106
+ // refresh (e.g. one triggered by `refreshProjectToken`).
107
+ const handle = {};
108
+ handle.promise = (async ()=>{
109
+ if (tokenStore.hasValidProjectToken({
110
+ projectInfo
111
+ })) {
112
+ const stored = tokenStore.getProjectToken({
113
+ projectInfo
114
+ });
115
+ if (stored?.token && inFlightRefreshes.get(cacheKey) === handle.promise) {
116
+ projectTokenCache.set(cacheKey, {
117
+ expiresAt: stored.expiresAt,
118
+ token: stored.token
119
+ });
120
+ return stored.token;
121
+ }
122
+ if (stored?.token) {
123
+ return stored.token;
124
+ }
125
+ // hasValidProjectToken said yes but getProjectToken returned no token —
126
+ // store was likely cleared by another process between calls. Fall through
127
+ // to fetch so the caller still gets a token.
128
+ log.warning(`Stored project token vanished between hasValidProjectToken and getProjectToken (cacheKey=${cacheKey}); re-fetching`);
129
+ }
130
+ let credential;
131
+ try {
132
+ credential = await getValidCredential(tokenStore);
133
+ } catch (error) {
134
+ throw new ProjectTokenError('Failed to get valid access token for project token refresh', error instanceof Error ? error : undefined);
135
+ }
136
+ if (!credential) {
137
+ return null;
138
+ }
139
+ let fetchedToken;
91
140
  try {
92
- validatedClaims = await validateProjectToken(projectToken.token, getEnvironment());
93
- } catch (validationError) {
94
- // Handle validation errors
95
- if (validationError instanceof JWTValidationError) {
96
- throw new ProjectTokenError(`Project token validation failed: ${validationError.message}`, validationError);
141
+ fetchedToken = await fetchProjectToken(credential, resolvedTenantId);
142
+ } catch (error) {
143
+ // Let API errors (e.g. FigmaApiError) propagate raw so callers can
144
+ // branch on status codes — but log context for debugging.
145
+ log.debug(`fetchProjectToken failed (cacheKey=${cacheKey}, tenantId=${resolvedTenantId}): ${error instanceof Error ? error.message : 'Unknown error'}`);
146
+ throw error;
147
+ }
148
+ const hasEnvToken = !!process.env.FIGMA_MOCK_PROJECT_TOKEN_VALUE;
149
+ const shouldMock = process.env.FIGMA_MOCK_PROJECT_TOKEN !== 'false';
150
+ let validatedClaims;
151
+ if (hasEnvToken || shouldMock) {
152
+ log.debug('Skipping JWT validation for mock/env project token');
153
+ validatedClaims = parseJWTClaims(fetchedToken.token);
154
+ } else {
155
+ try {
156
+ validatedClaims = await validateProjectToken(fetchedToken.token, getInfraEnvironment());
157
+ } catch (validationError) {
158
+ if (validationError instanceof JWTValidationError) {
159
+ throw new ProjectTokenError(`Project token validation failed: ${validationError.message}`, validationError);
160
+ }
161
+ throw validationError;
97
162
  }
98
- throw validationError;
163
+ }
164
+ if (typeof validatedClaims.exp !== 'number' || !Number.isFinite(validatedClaims.exp)) {
165
+ throw new ProjectTokenError('Project token missing or invalid expiration (exp) claim');
166
+ }
167
+ const expiresAt = validatedClaims.exp * 1000;
168
+ if (inFlightRefreshes.get(cacheKey) !== handle.promise) {
169
+ log.debug(`Project token refresh superseded; not persisting (cacheKey=${cacheKey})`);
170
+ return fetchedToken.token;
171
+ }
172
+ try {
173
+ tokenStore.setProjectToken({
174
+ projectInfo,
175
+ token: {
176
+ claims: validatedClaims,
177
+ expiresAt,
178
+ tenantId: resolvedTenantId,
179
+ token: fetchedToken.token
180
+ }
181
+ });
182
+ } catch (error) {
183
+ // Persistence is best-effort: a failure here (disk full, permissions,
184
+ // corrupt conf entry) shouldn't lose the freshly-minted token. Log and
185
+ // populate the in-memory cache so this process can still use it.
186
+ log.error(`Failed to persist project token to store (cacheKey=${cacheKey}): ${error instanceof Error ? error.message : 'Unknown error'}`);
187
+ }
188
+ projectTokenCache.set(cacheKey, {
189
+ expiresAt,
190
+ token: fetchedToken.token
191
+ });
192
+ return fetchedToken.token;
193
+ })();
194
+ inFlightRefreshes.set(cacheKey, handle.promise);
195
+ try {
196
+ return await handle.promise;
197
+ } finally{
198
+ if (inFlightRefreshes.get(cacheKey) === handle.promise) {
199
+ inFlightRefreshes.delete(cacheKey);
99
200
  }
100
201
  }
101
- // Ensure exp claim is present
102
- if (!validatedClaims.exp) {
103
- throw new ProjectTokenError('Project token missing expiration (exp) claim');
104
- }
105
- // Store the project token with validated expiration and claims
106
- tokenStore.setProjectToken(tenantId, {
107
- claims: validatedClaims,
108
- expiresAt: validatedClaims.exp * 1000,
109
- tenantId,
110
- token: projectToken.token
111
- });
112
- return projectToken.token;
113
202
  }
114
203
  /**
115
- * Refresh a project token for a tenant
204
+ * Force-refresh a project token, bypassing all cache layers.
116
205
  *
117
- * Forces a refresh of the project token even if the current one is still valid.
118
- * Useful for testing or when you want to ensure you have the freshest token.
206
+ * Invalidates the in-memory cache entry, the in-flight refresh promise (so a
207
+ * concurrently-running refresh that may already be returning a soon-to-be-stale
208
+ * token is dropped from the dedup map), and the persisted token store. Then
209
+ * delegates to {@link getValidProjectToken} to mint a fresh token.
119
210
  *
120
- * @param tokenStore - Token store for persisting tokens
121
- * @param tenantId - The tenant/CMS ID to refresh token for
211
+ * @param params.tokenStore - Token store for persisting tokens
212
+ * @param params.tenantId - Optional tenant/CMS ID; resolved from stored bootstrap data when omitted
213
+ * @param params.projectInfo - Optional project scope (defaults to env vars)
122
214
  * @returns Promise resolving to JWT token string or null if failed
123
215
  * @throws {ProjectTokenError} If token refresh fails
124
- */ export async function refreshProjectToken(tokenStore, tenantId) {
125
- // Clear the existing project token to force a refresh
126
- tokenStore.clearProjectToken(tenantId);
127
- // Get a new token (which will fetch from API since we just cleared it)
128
- return getValidProjectToken(tokenStore, tenantId);
216
+ */ export async function refreshProjectToken(params) {
217
+ const { projectInfo, tenantId, tokenStore } = params;
218
+ const resolvedTenantId = tenantId ?? tokenStore.getTenantId({
219
+ projectInfo
220
+ });
221
+ if (resolvedTenantId) {
222
+ const cacheKey = buildCacheKey({
223
+ projectInfo,
224
+ tenantId: resolvedTenantId
225
+ });
226
+ projectTokenCache.delete(cacheKey);
227
+ // Drop any in-flight refresh so getValidProjectToken below cannot return
228
+ // a soon-to-be-stale token via the dedup map.
229
+ inFlightRefreshes.delete(cacheKey);
230
+ }
231
+ tokenStore.clearProjectToken({
232
+ projectInfo
233
+ });
234
+ return getValidProjectToken(params);
129
235
  }
130
236
 
131
237
  //# sourceMappingURL=project-token.js.map
@@ -4,7 +4,8 @@ import type { FigmaTokens } from './types.js';
4
4
  */
5
5
  export declare class TokenRefreshError extends Error {
6
6
  statusCode?: number | undefined;
7
- constructor(message: string, statusCode?: number | undefined);
7
+ errorCode?: string | undefined;
8
+ constructor(message: string, statusCode?: number | undefined, errorCode?: string | undefined);
8
9
  }
9
10
  /**
10
11
  * Refresh an expired OAuth2 access token using a refresh token