@payloadcms/figma 0.0.1-alpha.9 → 0.1.0-alpha.1

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 (472) 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 +8215 -0
  64. package/dist/db-content-api/generated/content-api-types.js +5 -0
  65. package/dist/db-content-api/index.d.ts +40 -0
  66. package/dist/db-content-api/index.js +883 -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/clientVersionHeaders.d.ts +7 -0
  78. package/dist/db-content-api/utilities/clientVersionHeaders.js +15 -0
  79. package/dist/db-content-api/utilities/data/applyDefaults.d.ts +6 -0
  80. package/dist/db-content-api/utilities/data/applyDefaults.js +75 -0
  81. package/dist/db-content-api/utilities/data/atomicOperations.d.ts +16 -0
  82. package/dist/db-content-api/utilities/data/atomicOperations.js +48 -0
  83. package/dist/db-content-api/utilities/data/castFieldValue.d.ts +10 -0
  84. package/dist/db-content-api/utilities/data/castFieldValue.js +66 -0
  85. package/dist/db-content-api/utilities/data/convertRelationshipIds.d.ts +25 -0
  86. package/dist/db-content-api/utilities/data/convertRelationshipIds.js +109 -0
  87. package/dist/db-content-api/utilities/data/index.d.ts +48 -0
  88. package/dist/db-content-api/utilities/data/index.js +315 -0
  89. package/dist/db-content-api/utilities/data/isLocaleMap.d.ts +10 -0
  90. package/dist/db-content-api/utilities/data/isLocaleMap.js +13 -0
  91. package/dist/db-content-api/utilities/data/pointShape.d.ts +3 -0
  92. package/dist/db-content-api/utilities/data/pointShape.js +43 -0
  93. package/dist/db-content-api/utilities/data/removeVirtualFields.d.ts +11 -0
  94. package/dist/db-content-api/utilities/data/removeVirtualFields.js +52 -0
  95. package/dist/db-content-api/utilities/data/resolveFieldLocalization.d.ts +18 -0
  96. package/dist/db-content-api/utilities/data/resolveFieldLocalization.js +21 -0
  97. package/dist/db-content-api/utilities/data/richTextShape.d.ts +3 -0
  98. package/dist/db-content-api/utilities/data/richTextShape.js +56 -0
  99. package/dist/db-content-api/utilities/data/stripFields.d.ts +47 -0
  100. package/dist/db-content-api/utilities/data/stripFields.js +170 -0
  101. package/dist/db-content-api/utilities/data/transformPublishedLocale.d.ts +22 -0
  102. package/dist/db-content-api/utilities/data/transformPublishedLocale.js +40 -0
  103. package/dist/db-content-api/utilities/data/validateRelationships.d.ts +6 -0
  104. package/dist/db-content-api/utilities/data/validateRelationships.js +107 -0
  105. package/dist/db-content-api/utilities/joins.d.ts +50 -0
  106. package/dist/db-content-api/utilities/joins.js +124 -0
  107. package/dist/db-content-api/utilities/locale/index.d.ts +9 -0
  108. package/dist/db-content-api/utilities/locale/index.js +19 -0
  109. package/dist/db-content-api/utilities/meta/normalizeLocaleInWhere.d.ts +9 -0
  110. package/dist/db-content-api/utilities/meta/normalizeLocaleInWhere.js +100 -0
  111. package/dist/db-content-api/utilities/resolveBlocks.d.ts +19 -0
  112. package/dist/db-content-api/utilities/resolveBlocks.js +31 -0
  113. package/dist/db-content-api/utilities/schema/buildDocumentSchema.d.ts +72 -0
  114. package/dist/db-content-api/utilities/schema/buildDocumentSchema.js +264 -0
  115. package/dist/db-content-api/utilities/where.d.ts +9 -0
  116. package/dist/db-content-api/utilities/where.js +95 -0
  117. package/dist/deploy/schedule-extract-plugin.d.ts +10 -0
  118. package/dist/deploy/schedule-extract-plugin.js +32 -0
  119. package/dist/endpoints/health.d.ts +2 -0
  120. package/dist/endpoints/health.js +9 -0
  121. package/dist/endpoints/schema.d.ts +2 -0
  122. package/dist/endpoints/schema.js +27 -0
  123. package/dist/exports/client.d.ts +2 -1
  124. package/dist/exports/client.js +2 -2
  125. package/dist/index.d.ts +2 -2
  126. package/dist/index.js +3 -3
  127. package/dist/lib/download-skill.d.ts +12 -0
  128. package/dist/lib/download-skill.js +77 -0
  129. package/dist/oauth/components/FigmaAvatar/index.d.ts +3 -0
  130. package/dist/oauth/components/FigmaAvatar/index.js +25 -0
  131. package/dist/oauth/components/FigmaAvatar/index.scss +12 -0
  132. package/dist/oauth/components/FigmaAvatarCell/index.d.ts +4 -0
  133. package/dist/oauth/components/FigmaAvatarCell/index.js +23 -0
  134. package/dist/oauth/components/FigmaAvatarCell/index.scss +5 -0
  135. package/dist/oauth/components/FigmaAvatarPlaceholder/index.d.ts +8 -0
  136. package/dist/oauth/components/FigmaAvatarPlaceholder/index.js +35 -0
  137. package/dist/oauth/components/FigmaAvatarPlaceholder/index.scss +28 -0
  138. package/dist/oauth/components/LoginButton/iframeAutoLogin.d.ts +81 -0
  139. package/dist/oauth/components/LoginButton/iframeAutoLogin.js +168 -0
  140. package/dist/oauth/components/LoginButton/index.d.ts +0 -1
  141. package/dist/oauth/components/LoginButton/index.js +156 -18
  142. package/dist/oauth/components/LoginButton/index.scss +75 -3
  143. package/dist/oauth/components/LogoutButton/index.d.ts +0 -1
  144. package/dist/oauth/components/LogoutButton/index.js +20 -9
  145. package/dist/oauth/defaults.d.ts +3 -2
  146. package/dist/oauth/defaults.js +79 -12
  147. package/dist/oauth/endpoints/getLoginEndpoint.d.ts +0 -1
  148. package/dist/oauth/endpoints/getLoginEndpoint.js +87 -84
  149. package/dist/oauth/endpoints/getLogoutEndpoint.d.ts +0 -1
  150. package/dist/oauth/endpoints/getLogoutEndpoint.js +7 -6
  151. package/dist/oauth/endpoints/getMetaEndpoint.d.ts +0 -1
  152. package/dist/oauth/endpoints/getMetaEndpoint.js +18 -5
  153. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.d.ts +0 -1
  154. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js +11 -4
  155. package/dist/oauth/exports/client.d.ts +0 -1
  156. package/dist/oauth/exports/client.js +0 -2
  157. package/dist/oauth/hooks/afterLogout.d.ts +0 -1
  158. package/dist/oauth/hooks/afterLogout.js +0 -2
  159. package/dist/oauth/hooks/me.d.ts +0 -1
  160. package/dist/oauth/hooks/me.js +0 -2
  161. package/dist/oauth/hooks/refresh.d.ts +0 -1
  162. package/dist/oauth/hooks/refresh.js +2 -3
  163. package/dist/oauth/index.d.ts +0 -1
  164. package/dist/oauth/index.js +27 -7
  165. package/dist/oauth/strategy/index.d.ts +0 -3
  166. package/dist/oauth/strategy/index.js +55 -34
  167. package/dist/oauth/types.d.ts +23 -7
  168. package/dist/oauth/types.js +0 -2
  169. package/dist/oauth/utilities/buildUnauthorizedRedirect.d.ts +14 -0
  170. package/dist/oauth/utilities/buildUnauthorizedRedirect.js +28 -0
  171. package/dist/oauth/utilities/clearCookie.d.ts +0 -1
  172. package/dist/oauth/utilities/clearCookie.js +5 -3
  173. package/dist/oauth/utilities/createCookieOptions.d.ts +0 -1
  174. package/dist/oauth/utilities/createCookieOptions.js +9 -4
  175. package/dist/oauth/utilities/createDebugLogger.d.ts +0 -1
  176. package/dist/oauth/utilities/createDebugLogger.js +0 -2
  177. package/dist/oauth/utilities/establishSession.d.ts +22 -0
  178. package/dist/oauth/utilities/establishSession.js +80 -0
  179. package/dist/oauth/utilities/exchangeCodeForAccessToken.d.ts +23 -0
  180. package/dist/oauth/utilities/exchangeCodeForAccessToken.js +26 -0
  181. package/dist/oauth/utilities/extractOrigin.d.ts +0 -1
  182. package/dist/oauth/utilities/extractOrigin.js +0 -2
  183. package/dist/oauth/utilities/figmaHostnames.d.ts +2 -0
  184. package/dist/oauth/utilities/figmaHostnames.js +24 -0
  185. package/dist/oauth/utilities/getAdminCollectionSlug.d.ts +0 -1
  186. package/dist/oauth/utilities/getAdminCollectionSlug.js +0 -2
  187. package/dist/oauth/utilities/getAuthorizeURL.d.ts +65 -2
  188. package/dist/oauth/utilities/getAuthorizeURL.js +57 -4
  189. package/dist/oauth/utilities/getCookieExpiration.d.ts +0 -1
  190. package/dist/oauth/utilities/getCookieExpiration.js +0 -2
  191. package/dist/oauth/utilities/getSecondsFromTokenExp.d.ts +0 -1
  192. package/dist/oauth/utilities/getSecondsFromTokenExp.js +0 -2
  193. package/dist/oauth/utilities/getTokenExp.d.ts +0 -1
  194. package/dist/oauth/utilities/getTokenExp.js +0 -2
  195. package/dist/oauth/utilities/getUsernameField.d.ts +0 -1
  196. package/dist/oauth/utilities/getUsernameField.js +0 -2
  197. package/dist/oauth/utilities/hasUserTokenPropsChanged.d.ts +0 -1
  198. package/dist/oauth/utilities/hasUserTokenPropsChanged.js +0 -2
  199. package/dist/oauth/utilities/isAbsoluteURL.d.ts +1 -0
  200. package/dist/oauth/utilities/isAbsoluteURL.js +1 -0
  201. package/dist/oauth/utilities/isDuplicateKeyError.d.ts +6 -0
  202. package/dist/oauth/utilities/isDuplicateKeyError.js +12 -0
  203. package/dist/oauth/utilities/mergeHeaders.d.ts +0 -1
  204. package/dist/oauth/utilities/mergeHeaders.js +0 -2
  205. package/dist/oauth/utilities/refreshTokens.d.ts +0 -1
  206. package/dist/oauth/utilities/refreshTokens.js +21 -13
  207. package/dist/oauth/utilities/withPartitionedCookie.d.ts +19 -0
  208. package/dist/oauth/utilities/withPartitionedCookie.js +26 -0
  209. package/dist/oauth/utils/getSearchParam.d.ts +17 -0
  210. package/dist/oauth/utils/getSearchParam.js +22 -0
  211. package/dist/plugin/adapter.d.ts +0 -1
  212. package/dist/plugin/adapter.js +0 -2
  213. package/dist/plugin/auth-preflight.d.ts +7 -0
  214. package/dist/plugin/auth-preflight.js +18 -0
  215. package/dist/plugin/bootstrap-preflight.d.ts +22 -0
  216. package/dist/plugin/bootstrap-preflight.js +43 -0
  217. package/dist/plugin/build-config.d.ts +27 -15
  218. package/dist/plugin/build-config.js +380 -16
  219. package/dist/plugin/dev-cookie-names.d.ts +13 -0
  220. package/dist/plugin/dev-cookie-names.js +17 -0
  221. package/dist/scss.d.js +2 -0
  222. package/dist/storage-content-api/api-types.d.ts +183 -0
  223. package/dist/storage-content-api/api-types.js +4 -0
  224. package/dist/storage-content-api/client-uploads/generate.d.ts +14 -0
  225. package/dist/storage-content-api/client-uploads/generate.js +69 -0
  226. package/dist/storage-content-api/client.d.ts +5 -0
  227. package/dist/storage-content-api/client.js +37 -0
  228. package/dist/storage-content-api/generateURL.d.ts +6 -0
  229. package/dist/storage-content-api/generateURL.js +6 -0
  230. package/dist/storage-content-api/handleDelete.d.ts +7 -0
  231. package/dist/storage-content-api/handleDelete.js +15 -0
  232. package/dist/storage-content-api/handleUpload.d.ts +10 -0
  233. package/dist/storage-content-api/handleUpload.js +162 -0
  234. package/dist/storage-content-api/index.d.ts +4 -0
  235. package/dist/storage-content-api/index.js +37 -0
  236. package/dist/storage-content-api/staticHandler.d.ts +9 -0
  237. package/dist/storage-content-api/staticHandler.js +61 -0
  238. package/dist/storage-content-api/types.d.ts +9 -0
  239. package/dist/storage-content-api/types.js +1 -0
  240. package/dist/storage-content-api/utilities/getSafeFilename.d.ts +11 -0
  241. package/dist/storage-content-api/utilities/getSafeFilename.js +59 -0
  242. package/dist/storage-content-api/utilities/index.d.ts +2 -0
  243. package/dist/storage-content-api/utilities/index.js +2 -0
  244. package/dist/storage-content-api/utilities/parseUploadReference.d.ts +17 -0
  245. package/dist/storage-content-api/utilities/parseUploadReference.js +27 -0
  246. package/dist/templates/.env.example +5 -0
  247. package/dist/templates/README.md +19 -0
  248. package/dist/types/config.d.ts +2 -2
  249. package/dist/types/config.js +0 -4
  250. package/dist/types.d.ts +10 -2
  251. package/dist/types.js +0 -2
  252. package/dist/utils/adapters/nextjs.d.ts +8 -0
  253. package/dist/utils/adapters/nextjs.js +61 -0
  254. package/dist/utils/adapters/nitro.d.ts +8 -0
  255. package/dist/utils/adapters/nitro.js +172 -0
  256. package/dist/utils/adapters/vite.d.ts +9 -0
  257. package/dist/utils/adapters/vite.js +31 -0
  258. package/dist/utils/asset-collection.d.ts +27 -7
  259. package/dist/utils/asset-collection.js +59 -32
  260. package/dist/utils/build-detection.d.ts +5 -12
  261. package/dist/utils/build-detection.js +74 -13
  262. package/dist/utils/build-lambda-zip.d.ts +25 -0
  263. package/dist/utils/build-lambda-zip.js +90 -0
  264. package/dist/utils/cache-bootstrap.d.ts +7 -0
  265. package/dist/utils/cache-bootstrap.js +16 -0
  266. package/dist/utils/config.d.ts +0 -1
  267. package/dist/utils/config.js +1 -3
  268. package/dist/utils/deploy-adapter.d.ts +45 -0
  269. package/dist/utils/deploy-adapter.js +56 -0
  270. package/dist/utils/download-template.d.ts +9 -2
  271. package/dist/utils/download-template.js +24 -20
  272. package/dist/utils/env-management.d.ts +24 -8
  273. package/dist/utils/env-management.js +119 -66
  274. package/dist/utils/format-env-suffix.d.ts +11 -0
  275. package/dist/utils/format-env-suffix.js +11 -0
  276. package/dist/utils/format.d.ts +0 -1
  277. package/dist/utils/format.js +0 -2
  278. package/dist/utils/formatter.d.ts +0 -1
  279. package/dist/utils/formatter.js +23 -13
  280. package/dist/utils/fs-utils.d.ts +12 -0
  281. package/dist/utils/fs-utils.js +55 -0
  282. package/dist/utils/git.d.ts +0 -1
  283. package/dist/utils/git.js +0 -2
  284. package/dist/utils/handle-upgrade.d.ts +8 -0
  285. package/dist/utils/handle-upgrade.js +39 -0
  286. package/dist/utils/is-debug.d.ts +0 -1
  287. package/dist/utils/is-debug.js +0 -2
  288. package/dist/utils/lambda-config.d.ts +3 -2
  289. package/dist/utils/lambda-config.js +75 -80
  290. package/dist/utils/load-payload-config.d.ts +9 -0
  291. package/dist/utils/load-payload-config.js +27 -0
  292. package/dist/utils/log.d.ts +0 -1
  293. package/dist/utils/log.js +0 -2
  294. package/dist/utils/messages.d.ts +1 -3
  295. package/dist/utils/messages.js +47 -13
  296. package/dist/utils/package-manager.d.ts +24 -1
  297. package/dist/utils/package-manager.js +53 -2
  298. package/dist/utils/parse-template-spec.d.ts +11 -0
  299. package/dist/utils/parse-template-spec.js +60 -0
  300. package/dist/utils/payload-config-ast.d.ts +27 -7
  301. package/dist/utils/payload-config-ast.js +106 -60
  302. package/dist/utils/payload-config-finder.d.ts +2 -3
  303. package/dist/utils/payload-config-finder.js +48 -11
  304. package/dist/utils/payload-config-modifier.d.ts +1 -2
  305. package/dist/utils/payload-config-modifier.js +114 -68
  306. package/dist/utils/payload-package-check.d.ts +28 -3
  307. package/dist/utils/payload-package-check.js +90 -31
  308. package/dist/utils/project.d.ts +8 -4
  309. package/dist/utils/project.js +63 -37
  310. package/dist/utils/resolve-environment.d.ts +13 -0
  311. package/dist/utils/resolve-environment.js +29 -0
  312. package/dist/utils/s3-upload.d.ts +7 -3
  313. package/dist/utils/s3-upload.js +44 -9
  314. package/dist/utils/token-display.d.ts +5 -2
  315. package/dist/utils/token-display.js +49 -24
  316. package/dist/utils/typescript-validator.d.ts +0 -1
  317. package/dist/utils/typescript-validator.js +4 -8
  318. package/dist/utils/version-check.d.ts +2 -0
  319. package/dist/utils/version-check.js +43 -0
  320. package/package.json +47 -16
  321. package/dist/api/control-plane.d.ts.map +0 -1
  322. package/dist/api/control-plane.js.map +0 -1
  323. package/dist/api/figma-api.d.ts.map +0 -1
  324. package/dist/api/figma-api.js.map +0 -1
  325. package/dist/auth/browser.d.ts.map +0 -1
  326. package/dist/auth/browser.js.map +0 -1
  327. package/dist/auth/callback-server.d.ts.map +0 -1
  328. package/dist/auth/callback-server.js.map +0 -1
  329. package/dist/auth/crypto-utils.d.ts.map +0 -1
  330. package/dist/auth/crypto-utils.js.map +0 -1
  331. package/dist/auth/jwt-validator.d.ts.map +0 -1
  332. package/dist/auth/jwt-validator.js.map +0 -1
  333. package/dist/auth/oauth-flow.d.ts.map +0 -1
  334. package/dist/auth/oauth-flow.js.map +0 -1
  335. package/dist/auth/pkce.d.ts.map +0 -1
  336. package/dist/auth/pkce.js.map +0 -1
  337. package/dist/auth/project-token.d.ts.map +0 -1
  338. package/dist/auth/project-token.js.map +0 -1
  339. package/dist/auth/refresh.d.ts.map +0 -1
  340. package/dist/auth/refresh.js.map +0 -1
  341. package/dist/auth/token-store.d.ts.map +0 -1
  342. package/dist/auth/token-store.js.map +0 -1
  343. package/dist/auth/types.d.ts.map +0 -1
  344. package/dist/auth/types.js.map +0 -1
  345. package/dist/cli.d.ts.map +0 -1
  346. package/dist/cli.js.map +0 -1
  347. package/dist/commands/deploy.d.ts.map +0 -1
  348. package/dist/commands/deploy.js.map +0 -1
  349. package/dist/commands/init.d.ts.map +0 -1
  350. package/dist/commands/init.js.map +0 -1
  351. package/dist/commands/list-tokens.d.ts.map +0 -1
  352. package/dist/commands/list-tokens.js.map +0 -1
  353. package/dist/commands/login.d.ts.map +0 -1
  354. package/dist/commands/login.js.map +0 -1
  355. package/dist/commands/logout.d.ts.map +0 -1
  356. package/dist/commands/logout.js.map +0 -1
  357. package/dist/config/oauth.d.ts.map +0 -1
  358. package/dist/config/oauth.js.map +0 -1
  359. package/dist/constants.d.ts.map +0 -1
  360. package/dist/constants.js.map +0 -1
  361. package/dist/exports/client.d.ts.map +0 -1
  362. package/dist/exports/client.js.map +0 -1
  363. package/dist/index.d.ts.map +0 -1
  364. package/dist/index.js.map +0 -1
  365. package/dist/oauth/components/LoginButton/index.d.ts.map +0 -1
  366. package/dist/oauth/components/LoginButton/index.js.map +0 -1
  367. package/dist/oauth/components/LogoutButton/index.d.ts.map +0 -1
  368. package/dist/oauth/components/LogoutButton/index.js.map +0 -1
  369. package/dist/oauth/defaults.d.ts.map +0 -1
  370. package/dist/oauth/defaults.js.map +0 -1
  371. package/dist/oauth/endpoints/getLoginEndpoint.d.ts.map +0 -1
  372. package/dist/oauth/endpoints/getLoginEndpoint.js.map +0 -1
  373. package/dist/oauth/endpoints/getLogoutEndpoint.d.ts.map +0 -1
  374. package/dist/oauth/endpoints/getLogoutEndpoint.js.map +0 -1
  375. package/dist/oauth/endpoints/getMetaEndpoint.d.ts.map +0 -1
  376. package/dist/oauth/endpoints/getMetaEndpoint.js.map +0 -1
  377. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.d.ts.map +0 -1
  378. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js.map +0 -1
  379. package/dist/oauth/exports/client.d.ts.map +0 -1
  380. package/dist/oauth/exports/client.js.map +0 -1
  381. package/dist/oauth/hooks/afterLogout.d.ts.map +0 -1
  382. package/dist/oauth/hooks/afterLogout.js.map +0 -1
  383. package/dist/oauth/hooks/me.d.ts.map +0 -1
  384. package/dist/oauth/hooks/me.js.map +0 -1
  385. package/dist/oauth/hooks/refresh.d.ts.map +0 -1
  386. package/dist/oauth/hooks/refresh.js.map +0 -1
  387. package/dist/oauth/index.d.ts.map +0 -1
  388. package/dist/oauth/index.js.map +0 -1
  389. package/dist/oauth/strategy/index.d.ts.map +0 -1
  390. package/dist/oauth/strategy/index.js.map +0 -1
  391. package/dist/oauth/types.d.ts.map +0 -1
  392. package/dist/oauth/types.js.map +0 -1
  393. package/dist/oauth/utilities/clearCookie.d.ts.map +0 -1
  394. package/dist/oauth/utilities/clearCookie.js.map +0 -1
  395. package/dist/oauth/utilities/createCookieOptions.d.ts.map +0 -1
  396. package/dist/oauth/utilities/createCookieOptions.js.map +0 -1
  397. package/dist/oauth/utilities/createDebugLogger.d.ts.map +0 -1
  398. package/dist/oauth/utilities/createDebugLogger.js.map +0 -1
  399. package/dist/oauth/utilities/extractOrigin.d.ts.map +0 -1
  400. package/dist/oauth/utilities/extractOrigin.js.map +0 -1
  401. package/dist/oauth/utilities/getAdminCollectionSlug.d.ts.map +0 -1
  402. package/dist/oauth/utilities/getAdminCollectionSlug.js.map +0 -1
  403. package/dist/oauth/utilities/getAdminPath.d.ts +0 -8
  404. package/dist/oauth/utilities/getAdminPath.d.ts.map +0 -1
  405. package/dist/oauth/utilities/getAdminPath.js +0 -9
  406. package/dist/oauth/utilities/getAdminPath.js.map +0 -1
  407. package/dist/oauth/utilities/getAuthorizeURL.d.ts.map +0 -1
  408. package/dist/oauth/utilities/getAuthorizeURL.js.map +0 -1
  409. package/dist/oauth/utilities/getCookieExpiration.d.ts.map +0 -1
  410. package/dist/oauth/utilities/getCookieExpiration.js.map +0 -1
  411. package/dist/oauth/utilities/getSecondsFromTokenExp.d.ts.map +0 -1
  412. package/dist/oauth/utilities/getSecondsFromTokenExp.js.map +0 -1
  413. package/dist/oauth/utilities/getTokenExp.d.ts.map +0 -1
  414. package/dist/oauth/utilities/getTokenExp.js.map +0 -1
  415. package/dist/oauth/utilities/getUsernameField.d.ts.map +0 -1
  416. package/dist/oauth/utilities/getUsernameField.js.map +0 -1
  417. package/dist/oauth/utilities/hasUserTokenPropsChanged.d.ts.map +0 -1
  418. package/dist/oauth/utilities/hasUserTokenPropsChanged.js.map +0 -1
  419. package/dist/oauth/utilities/mergeHeaders.d.ts.map +0 -1
  420. package/dist/oauth/utilities/mergeHeaders.js.map +0 -1
  421. package/dist/oauth/utilities/refreshTokens.d.ts.map +0 -1
  422. package/dist/oauth/utilities/refreshTokens.js.map +0 -1
  423. package/dist/plugin/adapter.d.ts.map +0 -1
  424. package/dist/plugin/adapter.js.map +0 -1
  425. package/dist/plugin/build-config.d.ts.map +0 -1
  426. package/dist/plugin/build-config.js.map +0 -1
  427. package/dist/types/config.d.ts.map +0 -1
  428. package/dist/types/config.js.map +0 -1
  429. package/dist/types.d.ts.map +0 -1
  430. package/dist/types.js.map +0 -1
  431. package/dist/utils/asset-collection.d.ts.map +0 -1
  432. package/dist/utils/asset-collection.js.map +0 -1
  433. package/dist/utils/build-detection.d.ts.map +0 -1
  434. package/dist/utils/build-detection.js.map +0 -1
  435. package/dist/utils/config.d.ts.map +0 -1
  436. package/dist/utils/config.js.map +0 -1
  437. package/dist/utils/download-template.d.ts.map +0 -1
  438. package/dist/utils/download-template.js.map +0 -1
  439. package/dist/utils/env-management.d.ts.map +0 -1
  440. package/dist/utils/env-management.js.map +0 -1
  441. package/dist/utils/format.d.ts.map +0 -1
  442. package/dist/utils/format.js.map +0 -1
  443. package/dist/utils/formatter.d.ts.map +0 -1
  444. package/dist/utils/formatter.js.map +0 -1
  445. package/dist/utils/git.d.ts.map +0 -1
  446. package/dist/utils/git.js.map +0 -1
  447. package/dist/utils/is-debug.d.ts.map +0 -1
  448. package/dist/utils/is-debug.js.map +0 -1
  449. package/dist/utils/lambda-config.d.ts.map +0 -1
  450. package/dist/utils/lambda-config.js.map +0 -1
  451. package/dist/utils/log.d.ts.map +0 -1
  452. package/dist/utils/log.js.map +0 -1
  453. package/dist/utils/messages.d.ts.map +0 -1
  454. package/dist/utils/messages.js.map +0 -1
  455. package/dist/utils/package-manager.d.ts.map +0 -1
  456. package/dist/utils/package-manager.js.map +0 -1
  457. package/dist/utils/payload-config-ast.d.ts.map +0 -1
  458. package/dist/utils/payload-config-ast.js.map +0 -1
  459. package/dist/utils/payload-config-finder.d.ts.map +0 -1
  460. package/dist/utils/payload-config-finder.js.map +0 -1
  461. package/dist/utils/payload-config-modifier.d.ts.map +0 -1
  462. package/dist/utils/payload-config-modifier.js.map +0 -1
  463. package/dist/utils/payload-package-check.d.ts.map +0 -1
  464. package/dist/utils/payload-package-check.js.map +0 -1
  465. package/dist/utils/project.d.ts.map +0 -1
  466. package/dist/utils/project.js.map +0 -1
  467. package/dist/utils/s3-upload.d.ts.map +0 -1
  468. package/dist/utils/s3-upload.js.map +0 -1
  469. package/dist/utils/token-display.d.ts.map +0 -1
  470. package/dist/utils/token-display.js.map +0 -1
  471. package/dist/utils/typescript-validator.d.ts.map +0 -1
  472. package/dist/utils/typescript-validator.js.map +0 -1
@@ -1,63 +1,205 @@
1
1
  /* eslint-disable perfectionist/sort-classes */ import Conf from 'conf';
2
- import { TOKEN_EXPIRY_BUFFER_SECONDS } from '../config/oauth.js';
3
- import { deriveEncryptionKey } from './crypto-utils.js';
2
+ import envPaths from 'env-paths';
3
+ import fsSync from 'node:fs';
4
+ import path from 'node:path';
5
+ import { PROJECT_TOKEN_EXPIRY_BUFFER_SECONDS, TOKEN_EXPIRY_BUFFER_SECONDS } from '../config/oauth.js';
6
+ import { getInfraEnvironment } from '../constants.js';
7
+ import { getEnvVarSync } from '../utils/env-management.js';
8
+ import * as log from '../utils/log.js';
9
+ import { deriveEncryptionKey, deriveLegacyEncryptionKey } from './crypto-utils.js';
10
+ import { migrateOAuth, migrateProjectData, needsMigration } from './token-store-migration.js';
4
11
  /**
5
- * Secure storage manager for Figma OAuth2 tokens
6
- *
7
- * Uses the `conf` library to store tokens in an OS-specific secure location:
8
- * - macOS: ~/Library/Preferences/payloadcms-figma
9
- * - Linux: ~/.config/payloadcms-figma or $XDG_CONFIG_HOME/payloadcms-figma
10
- * - Windows: %APPDATA%/payloadcms-figma/Config
12
+ * Environment-keyed instances for singleton pattern.
13
+ */ const instances = {};
14
+ const OAUTH_STORE_SCHEMA_VERSION = 1;
15
+ const PROJECT_STORE_SCHEMA_VERSION = 1;
16
+ /**
17
+ * Get the singleton TokenStore instance for an environment.
18
+ */ export function getTokenStore(environment = getInfraEnvironment()) {
19
+ if (!instances[environment]) {
20
+ instances[environment] = new TokenStore({
21
+ environment
22
+ });
23
+ }
24
+ return instances[environment];
25
+ }
26
+ /**
27
+ * Secure storage manager for OAuth tokens and project-scoped bootstrap/token data.
11
28
  *
12
- * Tokens are encrypted at rest with a machine-specific key and file permissions
13
- * are set to 0600 (owner read/write only)
29
+ * For production code, use getTokenStore() to get the singleton instance.
30
+ * The constructor is still exported for test isolation.
14
31
  */ export class TokenStore {
15
- config;
32
+ baseConfigName;
33
+ deriveLegacyKey;
34
+ encryptionKey;
35
+ environment;
36
+ legacyRootDir;
37
+ oauthConfig;
38
+ projectName;
39
+ projectStoreConfigs = new Map();
16
40
  constructor(options){
17
- this.config = new Conf({
18
- configName: options?.configName || 'payloadcms-figma',
19
- projectName: 'payloadcms-figma',
20
- // Enable encryption with machine-specific key for better security
21
- encryptionKey: options?.encryptionKey || deriveEncryptionKey(),
22
- // Clear schema to avoid validation issues
23
- clearInvalidConfig: true
41
+ if (process.env.AWS_EXECUTION_ENV) {
42
+ throw new Error('TokenStore cannot be used in AWS Lambda environments');
43
+ }
44
+ const environment = options?.environment ?? 'production';
45
+ const projectName = 'payloadcms-figma';
46
+ const encryptionKey = options?.encryptionKey ?? deriveEncryptionKey();
47
+ const baseConfigName = options?.configName || projectName;
48
+ this.baseConfigName = baseConfigName;
49
+ this.deriveLegacyKey = options?.deriveLegacyKey ?? deriveLegacyEncryptionKey;
50
+ this.encryptionKey = encryptionKey;
51
+ this.environment = environment;
52
+ this.projectName = projectName;
53
+ // Resolve the legacy root dir (matching Conf's env-paths convention)
54
+ // without instantiating Conf, which would read/parse the encrypted file
55
+ // and could wipe it under clearInvalidConfig.
56
+ this.legacyRootDir = options?.rootDir ?? envPaths(projectName).config;
57
+ const legacyFilePath = path.join(this.legacyRootDir, `${baseConfigName}.json`);
58
+ const newOAuthCwd = this.buildOAuthStoreCwd();
59
+ const newOAuthFilePath = path.join(newOAuthCwd, `${this.buildOAuthConfigName()}.json`);
60
+ const resolveProjectStorePath = (scope)=>({
61
+ configName: this.buildProjectStoreConfigName(scope),
62
+ cwd: this.buildProjectStoreCwd(scope)
63
+ });
64
+ if (needsMigration({
65
+ legacyFilePath,
66
+ newOAuthFilePath
67
+ })) {
68
+ migrateOAuth({
69
+ encryptionKey,
70
+ legacyConfigName: baseConfigName,
71
+ newOAuthConfigName: this.buildOAuthConfigName(),
72
+ newOAuthCwd,
73
+ projectName
74
+ });
75
+ }
76
+ if (fsSync.existsSync(legacyFilePath)) {
77
+ migrateProjectData({
78
+ encryptionKey,
79
+ legacyConfigName: baseConfigName,
80
+ projectName,
81
+ resolveProjectStorePath
82
+ });
83
+ }
84
+ // Also check for legacy files in old environment-specific directories
85
+ // (e.g., payloadcms-figma-staging-nodejs/ for staging environment).
86
+ if (environment !== 'production') {
87
+ const oldEnvProjectName = `payloadcms-figma-${environment}`;
88
+ const oldEnvConfigName = options?.configName || oldEnvProjectName;
89
+ const oldEnvLegacyDir = options?.oldEnvLegacyDir ?? envPaths(oldEnvProjectName).config;
90
+ const oldEnvLegacyFilePath = path.join(oldEnvLegacyDir, `${oldEnvConfigName}.json`);
91
+ if (needsMigration({
92
+ legacyFilePath: oldEnvLegacyFilePath,
93
+ newOAuthFilePath
94
+ })) {
95
+ migrateOAuth({
96
+ encryptionKey,
97
+ legacyConfigName: oldEnvConfigName,
98
+ legacyCwd: oldEnvLegacyDir,
99
+ newOAuthConfigName: this.buildOAuthConfigName(),
100
+ newOAuthCwd,
101
+ projectName: oldEnvProjectName
102
+ });
103
+ }
104
+ if (fsSync.existsSync(oldEnvLegacyFilePath)) {
105
+ migrateProjectData({
106
+ encryptionKey,
107
+ legacyConfigName: oldEnvConfigName,
108
+ legacyCwd: oldEnvLegacyDir,
109
+ projectName: oldEnvProjectName,
110
+ resolveProjectStorePath
111
+ });
112
+ }
113
+ }
114
+ this.oauthConfig = this.createConfig({
115
+ configName: this.buildOAuthConfigName(),
116
+ cwd: this.buildOAuthStoreCwd(),
117
+ encryptionKey: this.encryptionKey,
118
+ storeType: 'oauth'
24
119
  });
25
120
  }
26
- /**
27
- * Retrieve stored tokens
28
- * @returns FigmaTokens if stored, null otherwise
29
- */ getTokens() {
30
- const tokens = this.config.get('tokens');
31
- return tokens || null;
121
+ getOauthInfo() {
122
+ const accessToken = this.safeGet({
123
+ config: this.oauthConfig,
124
+ key: 'accessToken'
125
+ });
126
+ const expiresAt = this.safeGet({
127
+ config: this.oauthConfig,
128
+ key: 'expiresAt'
129
+ });
130
+ const refreshToken = this.safeGet({
131
+ config: this.oauthConfig,
132
+ key: 'refreshToken'
133
+ });
134
+ if (typeof accessToken !== 'string' || typeof expiresAt !== 'number' || typeof refreshToken !== 'string') {
135
+ return null;
136
+ }
137
+ return {
138
+ accessToken,
139
+ expiresAt,
140
+ refreshToken,
141
+ scopes: this.safeGet({
142
+ config: this.oauthConfig,
143
+ key: 'scopes'
144
+ }),
145
+ tokenType: this.safeGet({
146
+ config: this.oauthConfig,
147
+ key: 'tokenType'
148
+ }),
149
+ userId: this.safeGet({
150
+ config: this.oauthConfig,
151
+ key: 'userId'
152
+ })
153
+ };
32
154
  }
33
- /**
34
- * Store OAuth2 tokens securely
35
- * @param tokens - Figma OAuth2 tokens to store
36
- */ setTokens(tokens) {
37
- this.config.set('tokens', tokens);
155
+ setTokens(tokens) {
156
+ this.oauthConfig.set('_schemaVersion', OAUTH_STORE_SCHEMA_VERSION);
157
+ this.oauthConfig.set('accessToken', tokens.accessToken);
158
+ this.oauthConfig.set('expiresAt', tokens.expiresAt);
159
+ this.oauthConfig.set('refreshToken', tokens.refreshToken);
160
+ if (tokens.scopes) {
161
+ this.oauthConfig.set('scopes', tokens.scopes);
162
+ } else {
163
+ this.oauthConfig.delete('scopes');
164
+ }
165
+ if (tokens.tokenType) {
166
+ this.oauthConfig.set('tokenType', tokens.tokenType);
167
+ } else {
168
+ this.oauthConfig.delete('tokenType');
169
+ }
170
+ if (tokens.userId) {
171
+ this.oauthConfig.set('userId', tokens.userId);
172
+ } else {
173
+ this.oauthConfig.delete('userId');
174
+ }
175
+ // Verify the round-trip: read back what we just wrote.
176
+ const readBack = this.getOauthInfo();
177
+ if (!readBack || readBack.accessToken !== tokens.accessToken) {
178
+ if (this.environment === 'staging') {
179
+ const filePath = this.oauthConfig.path;
180
+ const fileExists = fsSync.existsSync(filePath);
181
+ const fileSize = fileExists ? fsSync.statSync(filePath).size : 0;
182
+ log.warning(`Token verify-after-write FAILED. ` + `File: ${filePath}, exists: ${fileExists}, size: ${fileSize}B. ` + `Written accessToken starts: ${tokens.accessToken.substring(0, 10)}..., ` + `Read back: ${readBack ? readBack.accessToken.substring(0, 10) + '...' : 'null'}`);
183
+ }
184
+ }
38
185
  }
39
- /**
40
- * Clear all stored tokens (used for logout)
41
- */ clearTokens() {
42
- this.config.delete('tokens');
186
+ clearTokens() {
187
+ this.oauthConfig.delete('accessToken');
188
+ this.oauthConfig.delete('expiresAt');
189
+ this.oauthConfig.delete('refreshToken');
190
+ this.oauthConfig.delete('scopes');
191
+ this.oauthConfig.delete('tokenType');
192
+ this.oauthConfig.delete('userId');
43
193
  }
44
- /**
45
- * Check if valid (non-expired) tokens exist
46
- * @returns true if tokens exist and are not expired
47
- */ hasValidTokens() {
48
- const tokens = this.getTokens();
194
+ hasValidOauthToken() {
195
+ const tokens = this.getOauthInfo();
49
196
  if (!tokens) {
50
197
  return false;
51
198
  }
52
- return !this.isExpired();
199
+ return !this.isOauthExpired();
53
200
  }
54
- /**
55
- * Check if the current access token is expired
56
- * Includes a buffer time to avoid using tokens that are about to expire
57
- * @returns true if token is expired or will expire within buffer time
58
- */ isExpired() {
59
- // Access config directly to avoid circular dependency with getTokens()
60
- const tokens = this.config.get('tokens');
201
+ isOauthExpired() {
202
+ const tokens = this.getOauthInfo();
61
203
  if (!tokens) {
62
204
  return true;
63
205
  }
@@ -66,30 +208,19 @@ import { deriveEncryptionKey } from './crypto-utils.js';
66
208
  const expiryWithBuffer = tokens.expiresAt - bufferMs;
67
209
  return now >= expiryWithBuffer;
68
210
  }
69
- /**
70
- * Get the access token if it exists and is valid
71
- * @returns Access token string or null if expired/missing
72
- */ getAccessToken() {
73
- if (!this.hasValidTokens()) {
211
+ getCurrentOauthToken() {
212
+ if (!this.hasValidOauthToken()) {
74
213
  return null;
75
214
  }
76
- const tokens = this.getTokens();
215
+ const tokens = this.getOauthInfo();
77
216
  return tokens?.accessToken || null;
78
217
  }
79
- /**
80
- * Get the refresh token if it exists
81
- * @returns Refresh token string or null if missing
82
- */ getRefreshToken() {
83
- const tokens = this.getTokens();
218
+ getCurrentRefreshToken() {
219
+ const tokens = this.getOauthInfo();
84
220
  return tokens?.refreshToken || null;
85
221
  }
86
- /**
87
- * Update just the access token after a refresh
88
- * Preserves the existing refresh token and other metadata
89
- * @param accessToken - New access token
90
- * @param expiresIn - Expiration time in seconds
91
- */ updateAccessToken(accessToken, expiresIn) {
92
- const existingTokens = this.getTokens();
222
+ updateAccessToken(accessToken, expiresIn) {
223
+ const existingTokens = this.getOauthInfo();
93
224
  if (!existingTokens) {
94
225
  throw new Error('Cannot update access token: no existing tokens found');
95
226
  }
@@ -101,88 +232,238 @@ import { deriveEncryptionKey } from './crypto-utils.js';
101
232
  });
102
233
  }
103
234
  /**
104
- * Get the path to the config file (useful for debugging)
105
- * @returns Absolute path to the token storage file
235
+ * Returns the OAuth storage file path.
106
236
  */ getStoragePath() {
107
- return this.config.path;
237
+ return this.oauthConfig.path;
108
238
  }
109
- /**
110
- * Retrieve a project token for a specific tenant
111
- * Automatically removes expired tokens from storage
112
- * @param tenantId - The tenant/CMS ID
113
- * @returns ProjectToken if stored and valid, null otherwise
114
- */ getProjectToken(tenantId) {
115
- const projectTokens = this.config.get('projectTokens') || {};
116
- const projectToken = projectTokens[tenantId];
239
+ getProjectToken({ projectInfo } = {}) {
240
+ const resolvedProjectInfo = projectInfo ?? this.getProjectInfoFromEnv();
241
+ if (!resolvedProjectInfo) {
242
+ return null;
243
+ }
244
+ const config = this.getProjectStore(resolvedProjectInfo);
245
+ const projectToken = this.safeGet({
246
+ config,
247
+ key: 'projectToken'
248
+ });
117
249
  if (!projectToken) {
118
250
  return null;
119
251
  }
120
- // Auto-cleanup expired project token
121
252
  if (this.isProjectTokenExpired(projectToken)) {
122
- this.clearProjectToken(tenantId);
253
+ this.clearProjectToken({
254
+ projectInfo: resolvedProjectInfo
255
+ });
123
256
  return null;
124
257
  }
125
258
  return projectToken;
126
259
  }
127
- /**
128
- * Store a project token for a specific tenant
129
- * @param tenantId - The tenant/CMS ID
130
- * @param projectToken - The project token to store
131
- */ setProjectToken(tenantId, projectToken) {
132
- const projectTokens = this.config.get('projectTokens') || {};
133
- projectTokens[tenantId] = projectToken;
134
- this.config.set('projectTokens', projectTokens);
135
- }
136
- /**
137
- * Clear a project token for a specific tenant
138
- * @param tenantId - The tenant/CMS ID
139
- */ clearProjectToken(tenantId) {
140
- const projectTokens = this.config.get('projectTokens') || {};
141
- delete projectTokens[tenantId];
142
- this.config.set('projectTokens', projectTokens);
260
+ setProjectToken({ projectInfo, token }) {
261
+ const resolvedProjectInfo = projectInfo ?? this.getProjectInfoFromEnv();
262
+ if (!resolvedProjectInfo) {
263
+ throw new Error('Cannot set project token: FIGMA_PROJECT_ID and FIGMA_ENVIRONMENT_NAME must be set');
264
+ }
265
+ const config = this.getProjectStore(resolvedProjectInfo);
266
+ config.set('_schemaVersion', PROJECT_STORE_SCHEMA_VERSION);
267
+ config.set('projectToken', token);
143
268
  }
144
- /**
145
- * Clear all project tokens
146
- */ clearAllProjectTokens() {
147
- this.config.delete('projectTokens');
269
+ clearProjectToken({ projectInfo } = {}) {
270
+ const resolvedProjectInfo = projectInfo ?? this.getProjectInfoFromEnv();
271
+ if (!resolvedProjectInfo) {
272
+ return; // Nothing to clear if we can't determine the project
273
+ }
274
+ const config = this.getProjectStore(resolvedProjectInfo);
275
+ config.delete('projectToken');
148
276
  }
149
- /**
150
- * Check if a project token is expired
151
- * Includes a buffer time to avoid using tokens that are about to expire
152
- * @param projectToken - The project token to check
153
- * @returns true if token is expired or will expire within buffer time
154
- */ isProjectTokenExpired(projectToken) {
277
+ isProjectTokenExpired(token) {
155
278
  const now = Date.now();
156
- const bufferMs = TOKEN_EXPIRY_BUFFER_SECONDS * 1000;
157
- const expiryWithBuffer = projectToken.expiresAt - bufferMs;
279
+ const bufferMs = PROJECT_TOKEN_EXPIRY_BUFFER_SECONDS * 1000;
280
+ const expiryWithBuffer = token.expiresAt - bufferMs;
158
281
  return now >= expiryWithBuffer;
159
282
  }
160
- /**
161
- * Check if a valid (non-expired) project token exists for a tenant
162
- * @param tenantId - The tenant/CMS ID
163
- * @returns true if token exists and is not expired
164
- */ hasValidProjectToken(tenantId) {
165
- const projectToken = this.getProjectToken(tenantId);
283
+ hasValidProjectToken({ projectInfo } = {}) {
284
+ const projectToken = this.getProjectToken({
285
+ projectInfo
286
+ });
166
287
  if (!projectToken) {
167
288
  return false;
168
289
  }
169
290
  return !this.isProjectTokenExpired(projectToken);
170
291
  }
171
292
  /**
172
- * Get validated JWT claims from a project token
173
- * @param tenantId - The tenant/CMS ID
174
- * @returns JWT payload claims or null if token not found or has no claims
175
- */ getProjectTokenClaims(tenantId) {
176
- const projectToken = this.getProjectToken(tenantId);
177
- return projectToken?.claims || null;
293
+ * Get the tenantId (contentSystemId) for the project scope.
294
+ * Returns null if bootstrap data is not available.
295
+ */ getTenantId({ projectInfo } = {}) {
296
+ const resolvedProjectInfo = projectInfo ?? this.getProjectInfoFromEnv();
297
+ if (!resolvedProjectInfo) {
298
+ return null;
299
+ }
300
+ const bootstrapData = this.getBootstrapData(resolvedProjectInfo.projectId, resolvedProjectInfo.environmentName);
301
+ return bootstrapData?.contentSystemId ?? null;
178
302
  }
179
303
  /**
180
- * Get all tenant IDs that have stored project tokens
181
- * @returns Array of tenant IDs
182
- */ getAllProjectTokenTenantIds() {
183
- const projectTokens = this.config.get('projectTokens') || {};
184
- return Object.keys(projectTokens);
304
+ * Derive project info from environment variables.
305
+ * Returns null if either FIGMA_PROJECT_ID or FIGMA_ENVIRONMENT_NAME is not set.
306
+ */ getProjectInfoFromEnv() {
307
+ const projectId = process.env.FIGMA_PROJECT_ID || getEnvVarSync(process.cwd(), 'FIGMA_PROJECT_ID');
308
+ const environmentName = process.env.FIGMA_ENVIRONMENT_NAME || getEnvVarSync(process.cwd(), 'FIGMA_ENVIRONMENT_NAME');
309
+ if (!projectId || !environmentName) {
310
+ return null;
311
+ }
312
+ return {
313
+ environmentName,
314
+ projectId
315
+ };
316
+ }
317
+ getBootstrapData(projectId, environmentName) {
318
+ const config = this.getProjectStore({
319
+ environmentName,
320
+ projectId
321
+ });
322
+ const bootstrapData = this.safeGet({
323
+ config,
324
+ key: 'bootstrapData'
325
+ });
326
+ return bootstrapData || null;
327
+ }
328
+ setBootstrapData(projectId, environmentName, data) {
329
+ const config = this.getProjectStore({
330
+ environmentName,
331
+ projectId
332
+ });
333
+ config.set('_schemaVersion', PROJECT_STORE_SCHEMA_VERSION);
334
+ config.set('bootstrapData', data);
335
+ }
336
+ clearBootstrapData(projectId, environmentName) {
337
+ const config = this.getProjectStore({
338
+ environmentName,
339
+ projectId
340
+ });
341
+ config.delete('bootstrapData');
342
+ }
343
+ buildOAuthConfigName() {
344
+ // For test isolation: if using a custom config name, use it as-is with -oauth suffix
345
+ // Otherwise use the standard naming that includes environment
346
+ if (this.baseConfigName !== this.projectName) {
347
+ return `${this.baseConfigName}-oauth`;
348
+ }
349
+ return `payloadcms-figma-${this.environment}-oauth`;
350
+ }
351
+ buildOAuthStoreCwd() {
352
+ return path.join(this.getLegacyRootDir(), 'oauth');
353
+ }
354
+ buildProjectStoreConfigName(projectInfo) {
355
+ const env = this.sanitizeConfigSegment(projectInfo.environmentName);
356
+ if (this.baseConfigName !== this.projectName) {
357
+ return `${this.baseConfigName}-${env}-contentAPI`;
358
+ }
359
+ return `payloadcms-figma-${env}-contentAPI`;
360
+ }
361
+ buildProjectStoreCwd(projectInfo) {
362
+ return path.join(this.getLegacyRootDir(), 'projects', this.sanitizeConfigSegment(projectInfo.projectId));
363
+ }
364
+ sanitizeConfigSegment(value) {
365
+ return value.replace(/[^\w-]/g, '-').replace(/-+/g, '-');
366
+ }
367
+ projectInfoKey(projectInfo) {
368
+ return `${projectInfo.projectId}:${projectInfo.environmentName}`;
369
+ }
370
+ getLegacyRootDir() {
371
+ return this.legacyRootDir;
372
+ }
373
+ getProjectStore(projectInfo) {
374
+ const projectInfoKey = this.projectInfoKey(projectInfo);
375
+ const existing = this.projectStoreConfigs.get(projectInfoKey);
376
+ if (existing) {
377
+ return existing;
378
+ }
379
+ const config = this.createConfig({
380
+ configName: this.buildProjectStoreConfigName(projectInfo),
381
+ cwd: this.buildProjectStoreCwd(projectInfo),
382
+ encryptionKey: this.encryptionKey,
383
+ storeType: 'project'
384
+ });
385
+ this.projectStoreConfigs.set(projectInfoKey, config);
386
+ return config;
387
+ }
388
+ createConfig(params) {
389
+ const confOptions = {
390
+ clearInvalidConfig: false,
391
+ configName: params.configName,
392
+ cwd: params.cwd,
393
+ ...params.encryptionKey ? {
394
+ encryptionKey: params.encryptionKey
395
+ } : {},
396
+ projectName: this.projectName
397
+ };
398
+ try {
399
+ return new Conf(confOptions);
400
+ } catch (error) {
401
+ const migrated = this.tryMigrateLegacyKey(confOptions);
402
+ if (migrated) {
403
+ if (this.environment === 'staging') {
404
+ log.info('Successfully migrated local token cache.');
405
+ }
406
+ return migrated;
407
+ }
408
+ // Deserialization failed (e.g. encryption key changed).
409
+ // Log diagnostics, then clear and replace with a fresh store.
410
+ if (this.environment === 'staging') {
411
+ log.warning(`${params.storeType} token store corrupted, resetting. ` + `Error: ${error instanceof Error ? error.message : 'Unknown'}`);
412
+ }
413
+ const config = new Conf({
414
+ ...confOptions,
415
+ clearInvalidConfig: true
416
+ });
417
+ // Force a write so the corrupt file is replaced with an empty store.
418
+ // Without this, clearInvalidConfig only ignores bad reads in memory
419
+ // and the corrupt file persists, triggering this fallback every time.
420
+ config.clear();
421
+ return config;
422
+ }
423
+ }
424
+ tryMigrateLegacyKey(confOptions) {
425
+ if (!confOptions.encryptionKey) {
426
+ return null;
427
+ }
428
+ let snapshot;
429
+ try {
430
+ const legacyConf = new Conf({
431
+ ...confOptions,
432
+ clearInvalidConfig: false,
433
+ encryptionKey: this.deriveLegacyKey()
434
+ });
435
+ snapshot = {
436
+ ...legacyConf.store
437
+ };
438
+ } catch {
439
+ return null;
440
+ }
441
+ try {
442
+ const rewritten = new Conf({
443
+ ...confOptions,
444
+ clearInvalidConfig: true
445
+ });
446
+ rewritten.clear();
447
+ for (const [key, value] of Object.entries(snapshot)){
448
+ rewritten.set(key, value);
449
+ }
450
+ return rewritten;
451
+ } catch {
452
+ return null;
453
+ }
454
+ }
455
+ safeGet(params) {
456
+ const { config, key } = params;
457
+ try {
458
+ return config.get(key);
459
+ } catch (error) {
460
+ if (this.environment === 'staging') {
461
+ const filePath = config.path;
462
+ const fileExists = fsSync.existsSync(filePath);
463
+ const fileSize = fileExists ? fsSync.statSync(filePath).size : 0;
464
+ log.warning(`Token store read failed (key: ${String(key)}). ` + `File: ${filePath}, exists: ${fileExists}, size: ${fileSize}B. ` + `Error: ${error instanceof Error ? error.message : 'Unknown'}`);
465
+ }
466
+ return undefined;
467
+ }
185
468
  }
186
469
  }
187
-
188
- //# sourceMappingURL=token-store.js.map
@@ -1,5 +1,6 @@
1
1
  import type { ErrorResponsePayloadWithErrMessage, ErrorResponsePayloadWithErrorBoolean, User } from '@figma/rest-api-spec';
2
2
  import type { JWTPayload as JoseJWTPayload } from 'jose';
3
+ import type { Environment } from '../constants.js';
3
4
  /**
4
5
  * Standard OAuth2 scopes for user-level permissions
5
6
  * @see https://www.figma.com/developers/api#oauth2
@@ -105,12 +106,25 @@ export interface OAuthTokenRefreshParams {
105
106
  /**
106
107
  * Configuration for token storage
107
108
  */
108
- export interface TokenStoreConfig {
109
- /** Custom config name (defaults to 'payloadcms-figma') */
109
+ export type TokenStoreConfig = {
110
+ /** Config file name (for testing) */
110
111
  configName?: string;
111
- /** Enable encryption (defaults to true) */
112
+ /**
113
+ * Override for the legacy key derivation used by transparent migration.
114
+ * Tests pass an explicit function so they don't depend on the host machine's
115
+ * actual entropy. Production code leaves this undefined and the constructor
116
+ * falls back to `deriveLegacyEncryptionKey`.
117
+ */
118
+ deriveLegacyKey?: () => string;
119
+ /** Optional override for storage encryption key (primarily for tests). */
112
120
  encryptionKey?: string;
113
- }
121
+ /** Environment for config file naming */
122
+ environment?: Environment;
123
+ /** Override for the old per-environment legacy directory (primarily for tests). */
124
+ oldEnvLegacyDir?: string;
125
+ /** Override for the storage root directory (primarily for tests). */
126
+ rootDir?: string;
127
+ };
114
128
  /**
115
129
  * PKCE (Proof Key for Code Exchange) pair for OAuth2 public clients
116
130
  * @see https://datatracker.ietf.org/doc/html/rfc7636
@@ -158,6 +172,23 @@ export type FigmaErrorResponse = ErrorResponsePayloadWithErrMessage | ErrorRespo
158
172
  * Re-exported from @figma/rest-api-spec
159
173
  */
160
174
  export type FigmaUser = User;
175
+ /**
176
+ * Bootstrap data cached in the local encrypted store
177
+ * Keyed by projectId:environmentName
178
+ */
179
+ export type BootstrapData = {
180
+ contentSystemId: string;
181
+ oauthClientId: string;
182
+ oauthClientSecret: string;
183
+ tenantInstanceId: string;
184
+ };
185
+ /**
186
+ * Scope information used for project/environment-specific token storage.
187
+ */
188
+ export type ProjectStoreScope = {
189
+ environmentName: string;
190
+ projectId: string;
191
+ };
161
192
  /**
162
193
  * JWT payload structure from Figma project tokens
163
194
  * Extends jose's standard JWTPayload with Figma-specific claims
@@ -166,8 +197,12 @@ export interface JWTPayload extends JoseJWTPayload {
166
197
  [key: string]: unknown;
167
198
  /** User email address */
168
199
  email?: string;
200
+ /** Make permission tier the authed user holds on this CMS */
201
+ make_permission?: 'edit' | 'view';
169
202
  /** Tenant/CMS ID this token is scoped to */
170
203
  tenant_id?: string;
204
+ /** File user groups the authed user is a member of (scoped to the linked Make file) */
205
+ user_groups?: string[];
171
206
  }
172
207
  /**
173
208
  * Project token (JWT) for authenticating to Content API
@@ -185,7 +220,7 @@ export interface ProjectToken {
185
220
  }
186
221
  /**
187
222
  * Raw project token response from Figma API
188
- * Response from GET https://api.figma.com/v1/cms/:id/token/
223
+ * Response from POST https://api.figma.com/v1/cms/content-systems/:id/token/
189
224
  */
190
225
  export interface ProjectTokenResponse {
191
226
  /** Response metadata containing the JWT token */
@@ -194,4 +229,3 @@ export interface ProjectTokenResponse {
194
229
  token: string;
195
230
  };
196
231
  }
197
- //# sourceMappingURL=types.d.ts.map