@payloadcms/figma 0.0.1-alpha.1 → 0.0.1-alpha.11

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 (316) hide show
  1. package/dist/api/control-plane.d.ts.map +1 -1
  2. package/dist/api/control-plane.js +11 -16
  3. package/dist/api/control-plane.js.map +1 -1
  4. package/dist/api/figma-api.js +3 -3
  5. package/dist/api/figma-api.js.map +1 -1
  6. package/dist/auth/jwt-validator.js.map +1 -1
  7. package/dist/auth/oauth-flow.d.ts.map +1 -1
  8. package/dist/auth/oauth-flow.js +3 -6
  9. package/dist/auth/oauth-flow.js.map +1 -1
  10. package/dist/auth/project-token.d.ts.map +1 -1
  11. package/dist/auth/project-token.js +1 -4
  12. package/dist/auth/project-token.js.map +1 -1
  13. package/dist/auth/refresh.d.ts.map +1 -1
  14. package/dist/auth/refresh.js +19 -28
  15. package/dist/auth/refresh.js.map +1 -1
  16. package/dist/auth/types.d.ts +1 -1
  17. package/dist/auth/types.d.ts.map +1 -1
  18. package/dist/auth/types.js.map +1 -1
  19. package/dist/cli.js +1 -3
  20. package/dist/cli.js.map +1 -1
  21. package/dist/commands/deploy.d.ts.map +1 -1
  22. package/dist/commands/deploy.js +17 -10
  23. package/dist/commands/deploy.js.map +1 -1
  24. package/dist/commands/init.d.ts +4 -0
  25. package/dist/commands/init.d.ts.map +1 -1
  26. package/dist/commands/init.js +21 -85
  27. package/dist/commands/init.js.map +1 -1
  28. package/dist/commands/list-tokens.d.ts +1 -1
  29. package/dist/commands/list-tokens.d.ts.map +1 -1
  30. package/dist/commands/list-tokens.js +6 -5
  31. package/dist/commands/list-tokens.js.map +1 -1
  32. package/dist/commands/login.d.ts +2 -11
  33. package/dist/commands/login.d.ts.map +1 -1
  34. package/dist/commands/login.js +4 -7
  35. package/dist/commands/login.js.map +1 -1
  36. package/dist/commands/logout.d.ts +1 -1
  37. package/dist/commands/logout.js +1 -1
  38. package/dist/commands/logout.js.map +1 -1
  39. package/dist/db-adapter.d.ts +17 -0
  40. package/dist/db-adapter.d.ts.map +1 -0
  41. package/dist/db-adapter.js +757 -0
  42. package/dist/db-adapter.js.map +1 -0
  43. package/dist/endpoints/health.d.ts +3 -0
  44. package/dist/endpoints/health.d.ts.map +1 -0
  45. package/dist/endpoints/health.js +11 -0
  46. package/dist/endpoints/health.js.map +1 -0
  47. package/dist/exports/client.d.ts +3 -0
  48. package/dist/exports/client.d.ts.map +1 -0
  49. package/dist/exports/client.js +4 -0
  50. package/dist/exports/client.js.map +1 -0
  51. package/dist/oauth/components/LoginButton/index.d.ts +9 -0
  52. package/dist/oauth/components/LoginButton/index.d.ts.map +1 -0
  53. package/dist/oauth/components/LoginButton/index.js +52 -0
  54. package/dist/oauth/components/LoginButton/index.js.map +1 -0
  55. package/dist/oauth/components/LoginButton/index.scss +10 -0
  56. package/dist/oauth/components/LogoutButton/index.d.ts +7 -0
  57. package/dist/oauth/components/LogoutButton/index.d.ts.map +1 -0
  58. package/dist/oauth/components/LogoutButton/index.js +67 -0
  59. package/dist/oauth/components/LogoutButton/index.js.map +1 -0
  60. package/dist/oauth/components/LogoutButton/index.scss +10 -0
  61. package/dist/oauth/defaults.d.ts +10 -0
  62. package/dist/oauth/defaults.d.ts.map +1 -0
  63. package/dist/oauth/defaults.js +91 -0
  64. package/dist/oauth/defaults.js.map +1 -0
  65. package/dist/oauth/endpoints/getLoginEndpoint.d.ts +13 -0
  66. package/dist/oauth/endpoints/getLoginEndpoint.d.ts.map +1 -0
  67. package/dist/oauth/endpoints/getLoginEndpoint.js +237 -0
  68. package/dist/oauth/endpoints/getLoginEndpoint.js.map +1 -0
  69. package/dist/oauth/endpoints/getLogoutEndpoint.d.ts +12 -0
  70. package/dist/oauth/endpoints/getLogoutEndpoint.d.ts.map +1 -0
  71. package/dist/oauth/endpoints/getLogoutEndpoint.js +99 -0
  72. package/dist/oauth/endpoints/getLogoutEndpoint.js.map +1 -0
  73. package/dist/oauth/endpoints/getMetaEndpoint.d.ts +13 -0
  74. package/dist/oauth/endpoints/getMetaEndpoint.d.ts.map +1 -0
  75. package/dist/oauth/endpoints/getMetaEndpoint.js +25 -0
  76. package/dist/oauth/endpoints/getMetaEndpoint.js.map +1 -0
  77. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.d.ts +13 -0
  78. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.d.ts.map +1 -0
  79. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js +21 -0
  80. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js.map +1 -0
  81. package/dist/oauth/exports/client.d.ts +3 -0
  82. package/dist/oauth/exports/client.d.ts.map +1 -0
  83. package/dist/oauth/exports/client.js +4 -0
  84. package/dist/oauth/exports/client.js.map +1 -0
  85. package/dist/oauth/hooks/afterLogout.d.ts +8 -0
  86. package/dist/oauth/hooks/afterLogout.d.ts.map +1 -0
  87. package/dist/oauth/hooks/afterLogout.js +27 -0
  88. package/dist/oauth/hooks/afterLogout.js.map +1 -0
  89. package/dist/oauth/hooks/me.d.ts +5 -0
  90. package/dist/oauth/hooks/me.d.ts.map +1 -0
  91. package/dist/oauth/hooks/me.js +55 -0
  92. package/dist/oauth/hooks/me.js.map +1 -0
  93. package/dist/oauth/hooks/refresh.d.ts +8 -0
  94. package/dist/oauth/hooks/refresh.d.ts.map +1 -0
  95. package/dist/oauth/hooks/refresh.js +91 -0
  96. package/dist/oauth/hooks/refresh.js.map +1 -0
  97. package/dist/oauth/index.d.ts +4 -0
  98. package/dist/oauth/index.d.ts.map +1 -0
  99. package/dist/oauth/index.js +222 -0
  100. package/dist/oauth/index.js.map +1 -0
  101. package/dist/oauth/strategy/index.d.ts +54 -0
  102. package/dist/oauth/strategy/index.d.ts.map +1 -0
  103. package/dist/oauth/strategy/index.js +280 -0
  104. package/dist/oauth/strategy/index.js.map +1 -0
  105. package/dist/oauth/types.d.ts +192 -0
  106. package/dist/oauth/types.d.ts.map +1 -0
  107. package/dist/oauth/types.js +3 -0
  108. package/dist/oauth/types.js.map +1 -0
  109. package/dist/oauth/utilities/clearCookie.d.ts +9 -0
  110. package/dist/oauth/utilities/clearCookie.d.ts.map +1 -0
  111. package/dist/oauth/utilities/clearCookie.js +21 -0
  112. package/dist/oauth/utilities/clearCookie.js.map +1 -0
  113. package/dist/oauth/utilities/createCookieOptions.d.ts +10 -0
  114. package/dist/oauth/utilities/createCookieOptions.d.ts.map +1 -0
  115. package/dist/oauth/utilities/createCookieOptions.js +42 -0
  116. package/dist/oauth/utilities/createCookieOptions.js.map +1 -0
  117. package/dist/oauth/utilities/createDebugLogger.d.ts +4 -0
  118. package/dist/oauth/utilities/createDebugLogger.d.ts.map +1 -0
  119. package/dist/oauth/utilities/createDebugLogger.js +16 -0
  120. package/dist/oauth/utilities/createDebugLogger.js.map +1 -0
  121. package/dist/oauth/utilities/extractOrigin.d.ts +2 -0
  122. package/dist/oauth/utilities/extractOrigin.d.ts.map +1 -0
  123. package/dist/oauth/utilities/extractOrigin.js +12 -0
  124. package/dist/oauth/utilities/extractOrigin.js.map +1 -0
  125. package/dist/oauth/utilities/getAdminCollectionSlug.d.ts +3 -0
  126. package/dist/oauth/utilities/getAdminCollectionSlug.d.ts.map +1 -0
  127. package/dist/oauth/utilities/getAdminCollectionSlug.js +18 -0
  128. package/dist/oauth/utilities/getAdminCollectionSlug.js.map +1 -0
  129. package/dist/oauth/utilities/getAdminPath.d.ts +8 -0
  130. package/dist/oauth/utilities/getAdminPath.d.ts.map +1 -0
  131. package/dist/oauth/utilities/getAdminPath.js +9 -0
  132. package/dist/oauth/utilities/getAdminPath.js.map +1 -0
  133. package/dist/oauth/utilities/getAuthorizeURL.d.ts +17 -0
  134. package/dist/oauth/utilities/getAuthorizeURL.d.ts.map +1 -0
  135. package/dist/oauth/utilities/getAuthorizeURL.js +45 -0
  136. package/dist/oauth/utilities/getAuthorizeURL.js.map +1 -0
  137. package/dist/oauth/utilities/getCookieExpiration.d.ts +4 -0
  138. package/dist/oauth/utilities/getCookieExpiration.d.ts.map +1 -0
  139. package/dist/oauth/utilities/getCookieExpiration.js +11 -0
  140. package/dist/oauth/utilities/getCookieExpiration.js.map +1 -0
  141. package/dist/oauth/utilities/getSecondsFromTokenExp.d.ts +2 -0
  142. package/dist/oauth/utilities/getSecondsFromTokenExp.d.ts.map +1 -0
  143. package/dist/oauth/utilities/getSecondsFromTokenExp.js +7 -0
  144. package/dist/oauth/utilities/getSecondsFromTokenExp.js.map +1 -0
  145. package/dist/oauth/utilities/getTokenExp.d.ts +6 -0
  146. package/dist/oauth/utilities/getTokenExp.d.ts.map +1 -0
  147. package/dist/oauth/utilities/getTokenExp.js +20 -0
  148. package/dist/oauth/utilities/getTokenExp.js.map +1 -0
  149. package/dist/oauth/utilities/getUsernameField.d.ts +9 -0
  150. package/dist/oauth/utilities/getUsernameField.d.ts.map +1 -0
  151. package/dist/oauth/utilities/getUsernameField.js +20 -0
  152. package/dist/oauth/utilities/getUsernameField.js.map +1 -0
  153. package/dist/oauth/utilities/hasUserTokenPropsChanged.d.ts +8 -0
  154. package/dist/oauth/utilities/hasUserTokenPropsChanged.d.ts.map +1 -0
  155. package/dist/oauth/utilities/hasUserTokenPropsChanged.js +25 -0
  156. package/dist/oauth/utilities/hasUserTokenPropsChanged.js.map +1 -0
  157. package/dist/oauth/utilities/mergeHeaders.d.ts +2 -0
  158. package/dist/oauth/utilities/mergeHeaders.d.ts.map +1 -0
  159. package/dist/oauth/utilities/mergeHeaders.js +37 -0
  160. package/dist/oauth/utilities/mergeHeaders.js.map +1 -0
  161. package/dist/oauth/utilities/refreshTokens.d.ts +16 -0
  162. package/dist/oauth/utilities/refreshTokens.d.ts.map +1 -0
  163. package/dist/oauth/utilities/refreshTokens.js +67 -0
  164. package/dist/oauth/utilities/refreshTokens.js.map +1 -0
  165. package/dist/plugin/build-config.d.ts +7 -1
  166. package/dist/plugin/build-config.d.ts.map +1 -1
  167. package/dist/plugin/build-config.js +53 -3
  168. package/dist/plugin/build-config.js.map +1 -1
  169. package/dist/types/config.d.ts +0 -11
  170. package/dist/types/config.d.ts.map +1 -1
  171. package/dist/types/config.js +1 -1
  172. package/dist/types/config.js.map +1 -1
  173. package/dist/utils/config.d.ts +0 -22
  174. package/dist/utils/config.d.ts.map +1 -1
  175. package/dist/utils/config.js +0 -46
  176. package/dist/utils/config.js.map +1 -1
  177. package/dist/utils/messages.js +11 -11
  178. package/dist/utils/messages.js.map +1 -1
  179. package/dist/utils/payload-config-ast.d.ts +17 -1
  180. package/dist/utils/payload-config-ast.d.ts.map +1 -1
  181. package/dist/utils/payload-config-ast.js +166 -14
  182. package/dist/utils/payload-config-ast.js.map +1 -1
  183. package/dist/utils/payload-config-modifier.d.ts +2 -1
  184. package/dist/utils/payload-config-modifier.d.ts.map +1 -1
  185. package/dist/utils/payload-config-modifier.js +50 -79
  186. package/dist/utils/payload-config-modifier.js.map +1 -1
  187. package/dist/utils/payload-package-check.d.ts.map +1 -1
  188. package/dist/utils/payload-package-check.js +14 -33
  189. package/dist/utils/payload-package-check.js.map +1 -1
  190. package/dist/utils/project.d.ts +1 -1
  191. package/dist/utils/project.d.ts.map +1 -1
  192. package/dist/utils/project.js +3 -5
  193. package/dist/utils/project.js.map +1 -1
  194. package/dist/utils/s3-upload.d.ts.map +1 -1
  195. package/dist/utils/s3-upload.js +3 -8
  196. package/dist/utils/s3-upload.js.map +1 -1
  197. package/dist/utils/token-display.d.ts.map +1 -1
  198. package/dist/utils/token-display.js +3 -2
  199. package/dist/utils/token-display.js.map +1 -1
  200. package/package.json +9 -3
  201. package/dist/api/control-plane.spec.d.ts +0 -2
  202. package/dist/api/control-plane.spec.d.ts.map +0 -1
  203. package/dist/api/control-plane.spec.js +0 -296
  204. package/dist/api/control-plane.spec.js.map +0 -1
  205. package/dist/api/figma-api.spec.d.ts +0 -14
  206. package/dist/api/figma-api.spec.d.ts.map +0 -1
  207. package/dist/api/figma-api.spec.js +0 -201
  208. package/dist/api/figma-api.spec.js.map +0 -1
  209. package/dist/auth/__tests__/fixtures.d.ts +0 -26
  210. package/dist/auth/__tests__/fixtures.d.ts.map +0 -1
  211. package/dist/auth/__tests__/fixtures.js +0 -67
  212. package/dist/auth/__tests__/fixtures.js.map +0 -1
  213. package/dist/auth/__tests__/mocks.d.ts +0 -33
  214. package/dist/auth/__tests__/mocks.d.ts.map +0 -1
  215. package/dist/auth/__tests__/mocks.js +0 -63
  216. package/dist/auth/__tests__/mocks.js.map +0 -1
  217. package/dist/auth/callback-server.spec.d.ts +0 -2
  218. package/dist/auth/callback-server.spec.d.ts.map +0 -1
  219. package/dist/auth/callback-server.spec.js +0 -85
  220. package/dist/auth/callback-server.spec.js.map +0 -1
  221. package/dist/auth/crypto-utils.spec.d.ts +0 -2
  222. package/dist/auth/crypto-utils.spec.d.ts.map +0 -1
  223. package/dist/auth/crypto-utils.spec.js +0 -36
  224. package/dist/auth/crypto-utils.spec.js.map +0 -1
  225. package/dist/auth/jwt-validator.spec.d.ts +0 -10
  226. package/dist/auth/jwt-validator.spec.d.ts.map +0 -1
  227. package/dist/auth/jwt-validator.spec.js +0 -236
  228. package/dist/auth/jwt-validator.spec.js.map +0 -1
  229. package/dist/auth/oauth-flow.spec.d.ts +0 -2
  230. package/dist/auth/oauth-flow.spec.d.ts.map +0 -1
  231. package/dist/auth/oauth-flow.spec.js +0 -134
  232. package/dist/auth/oauth-flow.spec.js.map +0 -1
  233. package/dist/auth/pkce.spec.d.ts +0 -2
  234. package/dist/auth/pkce.spec.d.ts.map +0 -1
  235. package/dist/auth/pkce.spec.js +0 -32
  236. package/dist/auth/pkce.spec.js.map +0 -1
  237. package/dist/auth/project-token.spec.d.ts +0 -2
  238. package/dist/auth/project-token.spec.d.ts.map +0 -1
  239. package/dist/auth/project-token.spec.js +0 -332
  240. package/dist/auth/project-token.spec.js.map +0 -1
  241. package/dist/auth/refresh.spec.d.ts +0 -2
  242. package/dist/auth/refresh.spec.d.ts.map +0 -1
  243. package/dist/auth/refresh.spec.js +0 -105
  244. package/dist/auth/refresh.spec.js.map +0 -1
  245. package/dist/auth/token-store.spec.d.ts +0 -2
  246. package/dist/auth/token-store.spec.d.ts.map +0 -1
  247. package/dist/auth/token-store.spec.js +0 -276
  248. package/dist/auth/token-store.spec.js.map +0 -1
  249. package/dist/commands/__tests__/test-utils.d.ts +0 -28
  250. package/dist/commands/__tests__/test-utils.d.ts.map +0 -1
  251. package/dist/commands/__tests__/test-utils.js +0 -34
  252. package/dist/commands/__tests__/test-utils.js.map +0 -1
  253. package/dist/commands/deploy.spec.d.ts +0 -2
  254. package/dist/commands/deploy.spec.d.ts.map +0 -1
  255. package/dist/commands/deploy.spec.js +0 -18
  256. package/dist/commands/deploy.spec.js.map +0 -1
  257. package/dist/commands/init.spec.d.ts +0 -2
  258. package/dist/commands/init.spec.d.ts.map +0 -1
  259. package/dist/commands/init.spec.js +0 -283
  260. package/dist/commands/init.spec.js.map +0 -1
  261. package/dist/plugin/build-config.spec.d.ts +0 -2
  262. package/dist/plugin/build-config.spec.d.ts.map +0 -1
  263. package/dist/plugin/build-config.spec.js +0 -72
  264. package/dist/plugin/build-config.spec.js.map +0 -1
  265. package/dist/utils/asset-collection.spec.d.ts +0 -2
  266. package/dist/utils/asset-collection.spec.d.ts.map +0 -1
  267. package/dist/utils/asset-collection.spec.js +0 -155
  268. package/dist/utils/asset-collection.spec.js.map +0 -1
  269. package/dist/utils/build-detection.spec.d.ts +0 -2
  270. package/dist/utils/build-detection.spec.d.ts.map +0 -1
  271. package/dist/utils/build-detection.spec.js +0 -110
  272. package/dist/utils/build-detection.spec.js.map +0 -1
  273. package/dist/utils/config.spec.d.ts +0 -2
  274. package/dist/utils/config.spec.d.ts.map +0 -1
  275. package/dist/utils/config.spec.js +0 -167
  276. package/dist/utils/config.spec.js.map +0 -1
  277. package/dist/utils/download-template.spec.d.ts +0 -2
  278. package/dist/utils/download-template.spec.d.ts.map +0 -1
  279. package/dist/utils/download-template.spec.js +0 -76
  280. package/dist/utils/download-template.spec.js.map +0 -1
  281. package/dist/utils/env-management.spec.d.ts +0 -2
  282. package/dist/utils/env-management.spec.d.ts.map +0 -1
  283. package/dist/utils/env-management.spec.js +0 -123
  284. package/dist/utils/env-management.spec.js.map +0 -1
  285. package/dist/utils/git.spec.d.ts +0 -2
  286. package/dist/utils/git.spec.d.ts.map +0 -1
  287. package/dist/utils/git.spec.js +0 -99
  288. package/dist/utils/git.spec.js.map +0 -1
  289. package/dist/utils/lambda-config.spec.d.ts +0 -2
  290. package/dist/utils/lambda-config.spec.d.ts.map +0 -1
  291. package/dist/utils/lambda-config.spec.js +0 -141
  292. package/dist/utils/lambda-config.spec.js.map +0 -1
  293. package/dist/utils/payload-config-ast.spec.d.ts +0 -2
  294. package/dist/utils/payload-config-ast.spec.d.ts.map +0 -1
  295. package/dist/utils/payload-config-ast.spec.js +0 -303
  296. package/dist/utils/payload-config-ast.spec.js.map +0 -1
  297. package/dist/utils/payload-config-modifier.int.spec.d.ts +0 -2
  298. package/dist/utils/payload-config-modifier.int.spec.d.ts.map +0 -1
  299. package/dist/utils/payload-config-modifier.int.spec.js +0 -116
  300. package/dist/utils/payload-config-modifier.int.spec.js.map +0 -1
  301. package/dist/utils/payload-config-modifier.spec.d.ts +0 -2
  302. package/dist/utils/payload-config-modifier.spec.d.ts.map +0 -1
  303. package/dist/utils/payload-config-modifier.spec.js +0 -162
  304. package/dist/utils/payload-config-modifier.spec.js.map +0 -1
  305. package/dist/utils/payload-package-check.spec.d.ts +0 -2
  306. package/dist/utils/payload-package-check.spec.d.ts.map +0 -1
  307. package/dist/utils/payload-package-check.spec.js +0 -148
  308. package/dist/utils/payload-package-check.spec.js.map +0 -1
  309. package/dist/utils/project.spec.d.ts +0 -2
  310. package/dist/utils/project.spec.d.ts.map +0 -1
  311. package/dist/utils/project.spec.js +0 -222
  312. package/dist/utils/project.spec.js.map +0 -1
  313. package/dist/utils/s3-upload.spec.d.ts +0 -2
  314. package/dist/utils/s3-upload.spec.d.ts.map +0 -1
  315. package/dist/utils/s3-upload.spec.js +0 -140
  316. package/dist/utils/s3-upload.spec.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/auth/refresh.ts"],"sourcesContent":["/* eslint-disable perfectionist/sort-objects */\nimport type { FigmaTokenResponse, FigmaTokens } from './types.js'\n\nimport { OAUTH_CONFIG } from '../config/oauth.js'\nimport { isDebug } from '../utils/is-debug.js'\nimport * as log from '../utils/log.js'\n\n/**\n * Error thrown when token refresh fails\n */\nexport class TokenRefreshError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n ) {\n super(message)\n this.name = 'TokenRefreshError'\n }\n}\n\n/**\n * Refresh an expired OAuth2 access token using a refresh token\n *\n * Makes a POST request to Figma's token endpoint with the refresh token\n * to obtain a new access token. Uses public client pattern (no client secret).\n *\n * @param refreshToken - The refresh token to use\n * @param clientId - OAuth2 client ID (defaults to config)\n * @returns Promise resolving to new tokens\n * @throws TokenRefreshError if refresh fails\n */\nexport async function refreshAccessToken(\n refreshToken: string,\n clientId: string = OAUTH_CONFIG.clientId,\n): Promise<FigmaTokens> {\n // Prepare form data for token refresh request (public client)\n const params = new URLSearchParams({\n client_id: clientId,\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n })\n\n try {\n const response = await fetch(OAUTH_CONFIG.refreshUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: params.toString(),\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new TokenRefreshError(\n `Token refresh failed: ${response.statusText}. ${errorText}`,\n response.status,\n )\n }\n\n const data = (await response.json()) as FigmaTokenResponse\n\n // Validate response contains required fields\n if (!data.access_token || !data.refresh_token || !data.expires_in) {\n throw new TokenRefreshError('Invalid token response: missing required fields')\n }\n\n // Convert response to our internal token format\n const expiresAt = Date.now() + data.expires_in * 1000\n\n return {\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt,\n userId: data.user_id_string,\n }\n } catch (error) {\n if (error instanceof TokenRefreshError) {\n throw error\n }\n\n // Handle network errors and other exceptions\n throw new TokenRefreshError(\n `Failed to refresh token: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n }\n}\n\n/**\n * Exchange an authorization code for OAuth2 tokens\n *\n * This is used during the initial OAuth flow after the user authorizes the app.\n * Uses public client pattern with PKCE (code verifier is required).\n *\n * @param code - Authorization code from OAuth callback\n * @param codeVerifier - PKCE code verifier (required for public clients)\n * @param redirectUri - Redirect URI used in the authorization request\n * @param clientId - OAuth2 client ID (defaults to config)\n * @returns Promise resolving to tokens\n * @throws TokenRefreshError if exchange fails\n */\nexport async function exchangeCodeForTokens(\n code: string,\n codeVerifier: string,\n redirectUri: string = OAUTH_CONFIG.redirectUri,\n clientId: string = OAUTH_CONFIG.clientId,\n): Promise<FigmaTokens> {\n // Prepare form data for token exchange (public client with PKCE)\n const params = new URLSearchParams({\n client_id: clientId,\n code,\n code_verifier: codeVerifier,\n grant_type: 'authorization_code',\n redirect_uri: redirectUri,\n })\n\n try {\n // Public client - no client secret or Basic Auth header needed\n // Security is provided by PKCE (code_verifier in the request body)\n const headers: Record<string, string> = {\n 'Content-Type': 'application/x-www-form-urlencoded',\n }\n\n // Debug logging\n if (isDebug()) {\n log.debug(\n `Token exchange request: ${JSON.stringify({\n url: OAUTH_CONFIG.tokenUrl,\n headers,\n body: params.toString(),\n })}`,\n )\n }\n\n const response = await fetch(OAUTH_CONFIG.tokenUrl, {\n method: 'POST',\n headers,\n body: params.toString(),\n })\n\n if (isDebug()) {\n log.debug(\n `Token exchange response: ${JSON.stringify({\n status: response.status,\n statusText: response.statusText,\n headers: Object.fromEntries(response.headers.entries()),\n })}`,\n )\n }\n\n if (!response.ok) {\n const errorText = await response.text()\n if (isDebug()) {\n log.debug(`Error response body: ${errorText}`)\n }\n throw new TokenRefreshError(\n `Token exchange failed: ${response.statusText}. ${errorText}`,\n response.status,\n )\n }\n\n const data = (await response.json()) as FigmaTokenResponse\n\n if (isDebug()) {\n log.debug(\n `Token response: ${JSON.stringify({\n access_token: data.access_token,\n token_type: data.token_type,\n expires_in: data.expires_in,\n scope: data.scope,\n user_id_string: data.user_id_string,\n refresh_token: data.refresh_token?.substring(0, 10) + '...',\n })}`,\n )\n }\n\n // Validate response contains required fields\n if (!data.access_token || !data.refresh_token || !data.expires_in) {\n throw new TokenRefreshError('Invalid token response: missing required fields')\n }\n\n // Convert response to our internal token format\n const expiresAt = Date.now() + data.expires_in * 1000\n\n return {\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt,\n userId: data.user_id_string,\n }\n } catch (error) {\n if (error instanceof TokenRefreshError) {\n throw error\n }\n\n // Handle network errors and other exceptions\n throw new TokenRefreshError(\n `Failed to exchange code for tokens: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n }\n}\n"],"names":["OAUTH_CONFIG","isDebug","log","TokenRefreshError","Error","message","statusCode","name","refreshAccessToken","refreshToken","clientId","params","URLSearchParams","client_id","grant_type","refresh_token","response","fetch","refreshUrl","method","headers","body","toString","ok","errorText","text","statusText","status","data","json","access_token","expires_in","expiresAt","Date","now","accessToken","userId","user_id_string","error","exchangeCodeForTokens","code","codeVerifier","redirectUri","code_verifier","redirect_uri","debug","JSON","stringify","url","tokenUrl","Object","fromEntries","entries","token_type","scope","substring"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/auth/refresh.ts"],"sourcesContent":["/* eslint-disable perfectionist/sort-objects */\nimport type { FigmaTokenResponse, FigmaTokens } from './types.js'\n\nimport { OAUTH_CONFIG } from '../config/oauth.js'\nimport * as log from '../utils/log.js'\n\n/**\n * Error thrown when token refresh fails\n */\nexport class TokenRefreshError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n ) {\n super(message)\n this.name = 'TokenRefreshError'\n }\n}\n\n/**\n * Refresh an expired OAuth2 access token using a refresh token\n *\n * Makes a POST request to Figma's token endpoint with the refresh token\n * to obtain a new access token. Uses public client pattern (no client secret).\n *\n * @param refreshToken - The refresh token to use\n * @param clientId - OAuth2 client ID (defaults to config)\n * @returns Promise resolving to new tokens\n * @throws TokenRefreshError if refresh fails\n */\nexport async function refreshAccessToken(\n refreshToken: string,\n clientId: string = OAUTH_CONFIG.clientId,\n): Promise<FigmaTokens> {\n // Prepare form data for token refresh request (public client)\n const params = new URLSearchParams({\n client_id: clientId,\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n })\n\n try {\n const response = await fetch(OAUTH_CONFIG.refreshUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: params.toString(),\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new TokenRefreshError(\n `Token refresh failed: ${response.statusText}. ${errorText}`,\n response.status,\n )\n }\n\n const data = (await response.json()) as FigmaTokenResponse\n\n // Validate response contains required fields\n if (!data.access_token || !data.refresh_token || !data.expires_in) {\n throw new TokenRefreshError('Invalid token response: missing required fields')\n }\n\n // Convert response to our internal token format\n const expiresAt = Date.now() + data.expires_in * 1000\n\n return {\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt,\n userId: data.user_id_string,\n }\n } catch (error) {\n if (error instanceof TokenRefreshError) {\n throw error\n }\n\n // Handle network errors and other exceptions\n throw new TokenRefreshError(\n `Failed to refresh token: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n }\n}\n\n/**\n * Exchange an authorization code for OAuth2 tokens\n *\n * This is used during the initial OAuth flow after the user authorizes the app.\n * Uses public client pattern with PKCE (code verifier is required).\n *\n * @param code - Authorization code from OAuth callback\n * @param codeVerifier - PKCE code verifier (required for public clients)\n * @param redirectUri - Redirect URI used in the authorization request\n * @param clientId - OAuth2 client ID (defaults to config)\n * @returns Promise resolving to tokens\n * @throws TokenRefreshError if exchange fails\n */\nexport async function exchangeCodeForTokens(\n code: string,\n codeVerifier: string,\n redirectUri: string = OAUTH_CONFIG.redirectUri,\n clientId: string = OAUTH_CONFIG.clientId,\n): Promise<FigmaTokens> {\n // Prepare form data for token exchange (public client with PKCE)\n const params = new URLSearchParams({\n client_id: clientId,\n code,\n code_verifier: codeVerifier,\n grant_type: 'authorization_code',\n redirect_uri: redirectUri,\n })\n\n try {\n // Public client - no client secret or Basic Auth header needed\n // Security is provided by PKCE (code_verifier in the request body)\n const headers: Record<string, string> = {\n 'Content-Type': 'application/x-www-form-urlencoded',\n }\n\n // Debug logging\n log.debug(\n `Token exchange request: ${JSON.stringify({\n url: OAUTH_CONFIG.tokenUrl,\n headers,\n body: params.toString(),\n })}`,\n )\n\n const response = await fetch(OAUTH_CONFIG.tokenUrl, {\n method: 'POST',\n headers,\n body: params.toString(),\n })\n\n log.debug(\n `Token exchange response: ${JSON.stringify({\n status: response.status,\n statusText: response.statusText,\n headers: Object.fromEntries(response.headers.entries()),\n })}`,\n )\n\n if (!response.ok) {\n const errorText = await response.text()\n log.debug(`Error response body: ${errorText}`)\n\n throw new TokenRefreshError(\n `Token exchange failed: ${response.statusText}. ${errorText}`,\n response.status,\n )\n }\n\n const data = (await response.json()) as FigmaTokenResponse\n\n log.debug(\n `Token response: ${JSON.stringify({\n access_token: data.access_token,\n token_type: data.token_type,\n expires_in: data.expires_in,\n scope: data.scope,\n user_id_string: data.user_id_string,\n refresh_token: data.refresh_token?.substring(0, 10) + '...',\n })}`,\n )\n\n // Validate response contains required fields\n if (!data.access_token || !data.refresh_token || !data.expires_in) {\n throw new TokenRefreshError('Invalid token response: missing required fields')\n }\n\n // Convert response to our internal token format\n const expiresAt = Date.now() + data.expires_in * 1000\n\n return {\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt,\n userId: data.user_id_string,\n }\n } catch (error) {\n if (error instanceof TokenRefreshError) {\n throw error\n }\n\n // Handle network errors and other exceptions\n throw new TokenRefreshError(\n `Failed to exchange code for tokens: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n }\n}\n"],"names":["OAUTH_CONFIG","log","TokenRefreshError","Error","message","statusCode","name","refreshAccessToken","refreshToken","clientId","params","URLSearchParams","client_id","grant_type","refresh_token","response","fetch","refreshUrl","method","headers","body","toString","ok","errorText","text","statusText","status","data","json","access_token","expires_in","expiresAt","Date","now","accessToken","userId","user_id_string","error","exchangeCodeForTokens","code","codeVerifier","redirectUri","code_verifier","redirect_uri","debug","JSON","stringify","url","tokenUrl","Object","fromEntries","entries","token_type","scope","substring"],"mappings":"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"}
@@ -174,7 +174,7 @@ export interface JWTPayload extends JoseJWTPayload {
174
174
  * Used by local Payload instances to make authenticated requests
175
175
  */
176
176
  export interface ProjectToken {
177
- /** Validated JWT claims (populated after validation) */
177
+ /** Validated JWT claims */
178
178
  claims?: JWTPayload;
179
179
  /** Unix timestamp (milliseconds) when the token expires (from validated exp claim) */
180
180
  expiresAt: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kCAAkC,EAClC,oCAAoC,EACpC,IAAI,EACL,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,MAAM,CAAA;AAExD;;;GAGG;AACH,MAAM,MAAM,eAAe,GACvB,mBAAmB,GACnB,oBAAoB,GACpB,qBAAqB,GACrB,mBAAmB,GACnB,yBAAyB,GACzB,0BAA0B,GAC1B,oBAAoB,GACpB,qBAAqB,GACrB,sBAAsB,GACtB,oBAAoB,GACpB,YAAY,GACZ,wBAAwB,GACxB,qBAAqB,GACrB,sBAAsB,GACtB,eAAe,GACf,2BAA2B,GAC3B,eAAe,GACf,gBAAgB,CAAA;AAEpB;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,uBAAuB,CAAA;AAExD;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,kBAAkB,CAAA;AAE7D;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAA;IACnB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAA;IACjB,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAA;IACpB,yCAAyC;IACzC,MAAM,CAAC,EAAE,eAAe,EAAE,CAAA;IAC1B,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,2BAA2B;IAC3B,aAAa,EAAE,MAAM,CAAA;IACrB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2BAA2B;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,iBAAiB;IACjB,KAAK,EACD,gBAAgB,GAChB,eAAe,GACf,iBAAiB,GACjB,eAAe,GACf,qBAAqB,GACrB,wBAAwB,CAAA;IAC5B,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,8DAA8D;IAC9D,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,gCAAgC;IAChC,YAAY,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAA;IACrB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAA;IACb,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,4CAA4C;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,+CAA+C;IAC/C,UAAU,EAAE,oBAAoB,CAAA;IAChC,sDAAsD;IACtD,YAAY,EAAE,MAAM,CAAA;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,0CAA0C;IAC1C,UAAU,EAAE,eAAe,CAAA;IAC3B,oBAAoB;IACpB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,gDAAgD;IAChD,aAAa,EAAE,MAAM,CAAA;IACrB,0CAA0C;IAC1C,mBAAmB,EAAE,MAAM,CAAA;IAC3B,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAA;CACrB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,gBAAgB,EAAE,MAAM,CAAA;IACxB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAA;IAChB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAA;IACnB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,+BAA+B;IAC/B,MAAM,EAAE,eAAe,EAAE,CAAA;IACzB,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;GAEG;AACH,YAAY,EAAE,kCAAkC,EAAE,oCAAoC,EAAE,IAAI,EAAE,CAAA;AAE9F;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAC1B,kCAAkC,GAClC,oCAAoC,CAAA;AAExC;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,IAAI,CAAA;AAE5B;;;GAGG;AACH,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IACtB,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAA;IACjB,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAA;IAChB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,iDAAiD;IACjD,IAAI,EAAE;QACJ,uBAAuB;QACvB,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;CACF"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/auth/types.ts"],"sourcesContent":["import type {\n ErrorResponsePayloadWithErrMessage,\n ErrorResponsePayloadWithErrorBoolean,\n User,\n} from '@figma/rest-api-spec'\nimport type { JWTPayload as JoseJWTPayload } from 'jose'\n\n/**\n * Standard OAuth2 scopes for user-level permissions\n * @see https://www.figma.com/developers/api#oauth2\n */\nexport type FigmaOAuthScope =\n | 'current_user:read' // Read user name, email, profile image\n | 'file_comments:read' // Read file comments\n | 'file_comments:write' // Post/delete comments and reactions\n | 'file_content:read' // Read file contents (nodes, editor type)\n | 'file_dev_resources:read' // Read dev resources\n | 'file_dev_resources:write' // Write dev resources\n | 'file_metadata:read' // Read file metadata\n | 'file_variables:read' // Read variables (Enterprise only)\n | 'file_variables:write' // Write variables (Enterprise only)\n | 'file_versions:read' // Read version history\n | 'files:read' // @deprecated Read files, projects, users\n | 'library_analytics:read' // Read library analytics\n | 'library_assets:read' // Read published components/styles data\n | 'library_content:read' // Read published components/styles\n | 'projects:read' // List projects and files\n | 'team_library_content:read' // Read team published content\n | 'webhooks:read' // Read webhook metadata\n | 'webhooks:write' // Create/manage webhooks\n\n/**\n * Organization-level OAuth2 scopes\n * Requires organization admin permissions\n */\nexport type FigmaOrgOAuthScope = 'org:activity_log_read' // Read organization activity logs\n\n/**\n * All valid Figma OAuth scopes\n */\nexport type FigmaScope = FigmaOAuthScope | FigmaOrgOAuthScope\n\n/**\n * OAuth tokens returned from Figma API (internal format)\n */\nexport interface FigmaTokens {\n /** OAuth2 access token for making authenticated API requests */\n accessToken: string\n /** Unix timestamp (milliseconds) when the access token expires */\n expiresAt: number\n /** OAuth2 refresh token for obtaining new access tokens */\n refreshToken: string\n /** OAuth scopes granted to this token */\n scopes?: FigmaOAuthScope[]\n /** Token type (typically \"Bearer\") */\n tokenType?: string\n /** Figma user ID string */\n userId?: string\n}\n\n/**\n * Raw token response from Figma OAuth2 token endpoint\n * Response from POST https://api.figma.com/v1/oauth/token\n */\nexport interface FigmaTokenResponse {\n /** OAuth2 access token */\n access_token: string\n /** Token expiration time in seconds */\n expires_in: number\n /** OAuth2 refresh token */\n refresh_token: string\n /** Space-separated list of granted scopes */\n scope?: string\n /** Token type (typically \"Bearer\") */\n token_type?: string\n /** Figma user ID string */\n user_id_string?: string\n}\n\n/**\n * OAuth2 error response\n * @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.2\n */\nexport interface OAuthErrorResponse {\n /** Error code */\n error:\n | 'invalid_client'\n | 'invalid_grant'\n | 'invalid_request'\n | 'invalid_scope'\n | 'unauthorized_client'\n | 'unsupported_grant_type'\n /** Human-readable error description */\n error_description?: string\n /** URI with error information */\n error_uri?: string\n}\n\n/**\n * Parameters for OAuth2 authorization URL\n */\nexport interface OAuthAuthorizationParams {\n /** OAuth2 client ID */\n client_id: string\n /** PKCE code challenge (optional but recommended) */\n code_challenge?: string\n /** PKCE code challenge method (must be S256 if using PKCE) */\n code_challenge_method?: 'S256'\n /** Redirect URI for callback */\n redirect_uri: string\n /** Response type (always \"code\" for authorization code flow) */\n response_type: 'code'\n /** Requested scopes (space-separated) */\n scope: string\n /** State parameter for CSRF protection */\n state: string\n}\n\n/**\n * Parameters for OAuth2 token exchange\n */\nexport interface OAuthTokenExchangeParams {\n /** Authorization code from callback */\n code: string\n /** PKCE code verifier (if PKCE was used) */\n code_verifier?: string\n /** Grant type (always \"authorization_code\") */\n grant_type: 'authorization_code'\n /** Redirect URI (must match authorization request) */\n redirect_uri: string\n}\n\n/**\n * Parameters for OAuth2 token refresh\n */\nexport interface OAuthTokenRefreshParams {\n /** Grant type (always \"refresh_token\") */\n grant_type: 'refresh_token'\n /** Refresh token */\n refresh_token: string\n}\n\n/**\n * Configuration for token storage\n */\nexport interface TokenStoreConfig {\n /** Custom config name (defaults to 'payloadcms-figma') */\n configName?: string\n /** Enable encryption (defaults to true) */\n encryptionKey?: string\n}\n\n/**\n * PKCE (Proof Key for Code Exchange) pair for OAuth2 public clients\n * @see https://datatracker.ietf.org/doc/html/rfc7636\n */\nexport interface PKCEPair {\n /** Code challenge derived from code verifier */\n codeChallenge: string\n /** Code challenge method (always S256) */\n codeChallengeMethod: 'S256'\n /** Code verifier - random string used to generate challenge */\n codeVerifier: string\n}\n\n/**\n * OAuth configuration for Figma API (public client with PKCE)\n *\n * This configuration is for a PUBLIC OAuth client that uses PKCE\n * (Proof Key for Code Exchange) instead of a client secret.\n * Public clients (like CLIs) cannot securely store client secrets.\n */\nexport interface OAuthConfig {\n /** Figma OAuth authorization URL */\n authorizationUrl: string\n /** OAuth2 client ID (public client) */\n clientId: string\n /** OAuth2 redirect URI for callback */\n redirectUri: string\n /** Figma OAuth token refresh URL */\n refreshUrl: string\n /** OAuth2 scopes to request */\n scopes: FigmaOAuthScope[]\n /** Figma OAuth token exchange URL */\n tokenUrl: string\n}\n\n/**\n * Re-export Figma's official types for convenience\n */\nexport type { ErrorResponsePayloadWithErrMessage, ErrorResponsePayloadWithErrorBoolean, User }\n\n/**\n * Type alias for Figma API error responses\n * Combines both error response formats from Figma's REST API\n */\nexport type FigmaErrorResponse =\n | ErrorResponsePayloadWithErrMessage\n | ErrorResponsePayloadWithErrorBoolean\n\n/**\n * Figma user information\n * Re-exported from @figma/rest-api-spec\n */\nexport type FigmaUser = User\n\n/**\n * JWT payload structure from Figma project tokens\n * Extends jose's standard JWTPayload with Figma-specific claims\n */\nexport interface JWTPayload extends JoseJWTPayload {\n [key: string]: unknown\n /** User email address */\n email?: string\n /** Tenant/CMS ID this token is scoped to */\n tenant_id?: string\n}\n\n/**\n * Project token (JWT) for authenticating to Content API\n * Used by local Payload instances to make authenticated requests\n */\nexport interface ProjectToken {\n /** Validated JWT claims (populated after validation) */\n claims?: JWTPayload\n /** Unix timestamp (milliseconds) when the token expires (from validated exp claim) */\n expiresAt: number\n /** Tenant/CMS ID this token is scoped to */\n tenantId: string\n /** JWT token string signed by Figma API */\n token: string\n}\n\n/**\n * Raw project token response from Figma API\n * Response from GET https://api.figma.com/v1/cms/:id/token/\n */\nexport interface ProjectTokenResponse {\n /** Response metadata containing the JWT token */\n meta: {\n /** JWT token string */\n token: string\n }\n}\n"],"names":[],"mappings":"AAyOA;;;CAGC,GACD,WAMC"}
1
+ {"version":3,"sources":["../../src/auth/types.ts"],"sourcesContent":["import type {\n ErrorResponsePayloadWithErrMessage,\n ErrorResponsePayloadWithErrorBoolean,\n User,\n} from '@figma/rest-api-spec'\nimport type { JWTPayload as JoseJWTPayload } from 'jose'\n\n/**\n * Standard OAuth2 scopes for user-level permissions\n * @see https://www.figma.com/developers/api#oauth2\n */\nexport type FigmaOAuthScope =\n | 'current_user:read' // Read user name, email, profile image\n | 'file_comments:read' // Read file comments\n | 'file_comments:write' // Post/delete comments and reactions\n | 'file_content:read' // Read file contents (nodes, editor type)\n | 'file_dev_resources:read' // Read dev resources\n | 'file_dev_resources:write' // Write dev resources\n | 'file_metadata:read' // Read file metadata\n | 'file_variables:read' // Read variables (Enterprise only)\n | 'file_variables:write' // Write variables (Enterprise only)\n | 'file_versions:read' // Read version history\n | 'files:read' // @deprecated Read files, projects, users\n | 'library_analytics:read' // Read library analytics\n | 'library_assets:read' // Read published components/styles data\n | 'library_content:read' // Read published components/styles\n | 'projects:read' // List projects and files\n | 'team_library_content:read' // Read team published content\n | 'webhooks:read' // Read webhook metadata\n | 'webhooks:write' // Create/manage webhooks\n\n/**\n * Organization-level OAuth2 scopes\n * Requires organization admin permissions\n */\nexport type FigmaOrgOAuthScope = 'org:activity_log_read' // Read organization activity logs\n\n/**\n * All valid Figma OAuth scopes\n */\nexport type FigmaScope = FigmaOAuthScope | FigmaOrgOAuthScope\n\n/**\n * OAuth tokens returned from Figma API (internal format)\n */\nexport interface FigmaTokens {\n /** OAuth2 access token for making authenticated API requests */\n accessToken: string\n /** Unix timestamp (milliseconds) when the access token expires */\n expiresAt: number\n /** OAuth2 refresh token for obtaining new access tokens */\n refreshToken: string\n /** OAuth scopes granted to this token */\n scopes?: FigmaOAuthScope[]\n /** Token type (typically \"Bearer\") */\n tokenType?: string\n /** Figma user ID string */\n userId?: string\n}\n\n/**\n * Raw token response from Figma OAuth2 token endpoint\n * Response from POST https://api.figma.com/v1/oauth/token\n */\nexport interface FigmaTokenResponse {\n /** OAuth2 access token */\n access_token: string\n /** Token expiration time in seconds */\n expires_in: number\n /** OAuth2 refresh token */\n refresh_token: string\n /** Space-separated list of granted scopes */\n scope?: string\n /** Token type (typically \"Bearer\") */\n token_type?: string\n /** Figma user ID string */\n user_id_string?: string\n}\n\n/**\n * OAuth2 error response\n * @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.2\n */\nexport interface OAuthErrorResponse {\n /** Error code */\n error:\n | 'invalid_client'\n | 'invalid_grant'\n | 'invalid_request'\n | 'invalid_scope'\n | 'unauthorized_client'\n | 'unsupported_grant_type'\n /** Human-readable error description */\n error_description?: string\n /** URI with error information */\n error_uri?: string\n}\n\n/**\n * Parameters for OAuth2 authorization URL\n */\nexport interface OAuthAuthorizationParams {\n /** OAuth2 client ID */\n client_id: string\n /** PKCE code challenge (optional but recommended) */\n code_challenge?: string\n /** PKCE code challenge method (must be S256 if using PKCE) */\n code_challenge_method?: 'S256'\n /** Redirect URI for callback */\n redirect_uri: string\n /** Response type (always \"code\" for authorization code flow) */\n response_type: 'code'\n /** Requested scopes (space-separated) */\n scope: string\n /** State parameter for CSRF protection */\n state: string\n}\n\n/**\n * Parameters for OAuth2 token exchange\n */\nexport interface OAuthTokenExchangeParams {\n /** Authorization code from callback */\n code: string\n /** PKCE code verifier (if PKCE was used) */\n code_verifier?: string\n /** Grant type (always \"authorization_code\") */\n grant_type: 'authorization_code'\n /** Redirect URI (must match authorization request) */\n redirect_uri: string\n}\n\n/**\n * Parameters for OAuth2 token refresh\n */\nexport interface OAuthTokenRefreshParams {\n /** Grant type (always \"refresh_token\") */\n grant_type: 'refresh_token'\n /** Refresh token */\n refresh_token: string\n}\n\n/**\n * Configuration for token storage\n */\nexport interface TokenStoreConfig {\n /** Custom config name (defaults to 'payloadcms-figma') */\n configName?: string\n /** Enable encryption (defaults to true) */\n encryptionKey?: string\n}\n\n/**\n * PKCE (Proof Key for Code Exchange) pair for OAuth2 public clients\n * @see https://datatracker.ietf.org/doc/html/rfc7636\n */\nexport interface PKCEPair {\n /** Code challenge derived from code verifier */\n codeChallenge: string\n /** Code challenge method (always S256) */\n codeChallengeMethod: 'S256'\n /** Code verifier - random string used to generate challenge */\n codeVerifier: string\n}\n\n/**\n * OAuth configuration for Figma API (public client with PKCE)\n *\n * This configuration is for a PUBLIC OAuth client that uses PKCE\n * (Proof Key for Code Exchange) instead of a client secret.\n * Public clients (like CLIs) cannot securely store client secrets.\n */\nexport interface OAuthConfig {\n /** Figma OAuth authorization URL */\n authorizationUrl: string\n /** OAuth2 client ID (public client) */\n clientId: string\n /** OAuth2 redirect URI for callback */\n redirectUri: string\n /** Figma OAuth token refresh URL */\n refreshUrl: string\n /** OAuth2 scopes to request */\n scopes: FigmaOAuthScope[]\n /** Figma OAuth token exchange URL */\n tokenUrl: string\n}\n\n/**\n * Re-export Figma's official types for convenience\n */\nexport type { ErrorResponsePayloadWithErrMessage, ErrorResponsePayloadWithErrorBoolean, User }\n\n/**\n * Type alias for Figma API error responses\n * Combines both error response formats from Figma's REST API\n */\nexport type FigmaErrorResponse =\n | ErrorResponsePayloadWithErrMessage\n | ErrorResponsePayloadWithErrorBoolean\n\n/**\n * Figma user information\n * Re-exported from @figma/rest-api-spec\n */\nexport type FigmaUser = User\n\n/**\n * JWT payload structure from Figma project tokens\n * Extends jose's standard JWTPayload with Figma-specific claims\n */\nexport interface JWTPayload extends JoseJWTPayload {\n [key: string]: unknown\n /** User email address */\n email?: string\n /** Tenant/CMS ID this token is scoped to */\n tenant_id?: string\n}\n\n/**\n * Project token (JWT) for authenticating to Content API\n * Used by local Payload instances to make authenticated requests\n */\nexport interface ProjectToken {\n /** Validated JWT claims */\n claims?: JWTPayload\n /** Unix timestamp (milliseconds) when the token expires (from validated exp claim) */\n expiresAt: number\n /** Tenant/CMS ID this token is scoped to */\n tenantId: string\n /** JWT token string signed by Figma API */\n token: string\n}\n\n/**\n * Raw project token response from Figma API\n * Response from GET https://api.figma.com/v1/cms/:id/token/\n */\nexport interface ProjectTokenResponse {\n /** Response metadata containing the JWT token */\n meta: {\n /** JWT token string */\n token: string\n }\n}\n"],"names":[],"mappings":"AAyOA;;;CAGC,GACD,WAMC"}
package/dist/cli.js CHANGED
@@ -77,9 +77,7 @@ class Main {
77
77
  });
78
78
  break;
79
79
  case 'login':
80
- await loginCommand({
81
- debug: this.args['--debug']
82
- });
80
+ await loginCommand();
83
81
  break;
84
82
  case 'logout':
85
83
  await logoutCommand({
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport arg from 'arg'\nimport pc from 'picocolors'\n\nimport type { CliArgs } from './types.js'\n\nimport { deployCommand } from './commands/deploy.js'\nimport { initCommand } from './commands/init.js'\nimport { listTokensCommand } from './commands/list-tokens.js'\nimport { loginCommand } from './commands/login.js'\nimport { logoutCommand } from './commands/logout.js'\nimport { feedbackOutro, helpMessage } from './utils/messages.js'\n\n/**\n * Entrypoint for bin/cli.js\n */\nexport async function main(): Promise<void> {\n try {\n await new Main().init()\n } catch (e) {\n if (e instanceof Error) {\n // eslint-disable-next-line no-console\n console.error(e.message)\n }\n }\n}\n\nclass Main {\n args: CliArgs\n\n constructor() {\n // @ts-expect-error bad typings\n this.args = arg(\n {\n '--debug': Boolean,\n '--force': Boolean,\n '--help': Boolean,\n '--id': String,\n '--name': String,\n '--skip-auth': Boolean,\n '--yes': Boolean,\n\n // Aliases\n '-f': '--force',\n '-h': '--help',\n '-y': '--yes',\n },\n { permissive: true },\n )\n\n // Set debug flag globally\n if (this.args['--debug']) {\n process.env.DEBUG = 'true'\n }\n }\n\n async init(): Promise<void> {\n try {\n if (this.args['--help']) {\n helpMessage()\n process.exit(0)\n }\n\n // Get the subcommand (first non-flag argument)\n const subcommand = this.args._[0]\n\n // eslint-disable-next-line no-console\n console.log('\\n')\n p.intro(pc.bgCyan(pc.black(' @payloadcms/figma ')))\n\n // Route to appropriate command handler\n switch (subcommand) {\n case 'deploy':\n await deployCommand({\n debug: this.args['--debug'],\n yes: this.args['--yes'],\n })\n break\n\n case 'init':\n await initCommand({\n id: this.args['--id'],\n name: this.args['--name'],\n debug: this.args['--debug'],\n force: this.args['--force'],\n skipAuth: this.args['--skip-auth'],\n })\n break\n\n case 'list-tokens':\n listTokensCommand({\n debug: this.args['--debug'],\n })\n break\n\n case 'login':\n await loginCommand({\n debug: this.args['--debug'],\n })\n break\n\n case 'logout':\n await logoutCommand({\n debug: this.args['--debug'],\n })\n break\n\n case undefined:\n // No subcommand - show default message\n p.note(\"Let's create a new CMS!\")\n p.outro(feedbackOutro())\n break\n\n default:\n p.log.error(pc.red(`Unknown command: ${subcommand}`))\n p.note('Use --help to see available commands', 'Tip')\n process.exit(1)\n }\n\n process.exit(0)\n } catch (err: unknown) {\n // eslint-disable-next-line no-console\n console.error(err instanceof Error ? err.message : 'An error occurred')\n process.exit(1)\n }\n }\n}\n"],"names":["p","arg","pc","deployCommand","initCommand","listTokensCommand","loginCommand","logoutCommand","feedbackOutro","helpMessage","main","Main","init","e","Error","console","error","message","args","Boolean","String","permissive","process","env","DEBUG","exit","subcommand","_","log","intro","bgCyan","black","debug","yes","id","name","force","skipAuth","undefined","note","outro","red","err"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport arg from 'arg'\nimport pc from 'picocolors'\n\nimport type { CliArgs } from './types.js'\n\nimport { deployCommand } from './commands/deploy.js'\nimport { initCommand } from './commands/init.js'\nimport { listTokensCommand } from './commands/list-tokens.js'\nimport { loginCommand } from './commands/login.js'\nimport { logoutCommand } from './commands/logout.js'\nimport { feedbackOutro, helpMessage } from './utils/messages.js'\n\n/**\n * Entrypoint for bin/cli.js\n */\nexport async function main(): Promise<void> {\n try {\n await new Main().init()\n } catch (e) {\n if (e instanceof Error) {\n // eslint-disable-next-line no-console\n console.error(e.message)\n }\n }\n}\n\nclass Main {\n args: CliArgs\n\n constructor() {\n // @ts-expect-error bad typings\n this.args = arg(\n {\n '--debug': Boolean,\n '--force': Boolean,\n '--help': Boolean,\n '--id': String,\n '--name': String,\n '--skip-auth': Boolean,\n '--yes': Boolean,\n\n // Aliases\n '-f': '--force',\n '-h': '--help',\n '-y': '--yes',\n },\n { permissive: true },\n )\n\n // Set debug flag globally\n if (this.args['--debug']) {\n process.env.DEBUG = 'true'\n }\n }\n\n async init(): Promise<void> {\n try {\n if (this.args['--help']) {\n helpMessage()\n process.exit(0)\n }\n\n // Get the subcommand (first non-flag argument)\n const subcommand = this.args._[0]\n\n // eslint-disable-next-line no-console\n console.log('\\n')\n p.intro(pc.bgCyan(pc.black(' @payloadcms/figma ')))\n\n // Route to appropriate command handler\n switch (subcommand) {\n case 'deploy':\n await deployCommand({\n debug: this.args['--debug'],\n yes: this.args['--yes'],\n })\n break\n\n case 'init':\n await initCommand({\n id: this.args['--id'],\n name: this.args['--name'],\n debug: this.args['--debug'],\n force: this.args['--force'],\n skipAuth: this.args['--skip-auth'],\n })\n break\n\n case 'list-tokens':\n listTokensCommand({\n debug: this.args['--debug'],\n })\n break\n\n case 'login':\n await loginCommand()\n break\n\n case 'logout':\n await logoutCommand({\n debug: this.args['--debug'],\n })\n break\n\n case undefined:\n // No subcommand - show default message\n p.note(\"Let's create a new CMS!\")\n p.outro(feedbackOutro())\n break\n\n default:\n p.log.error(pc.red(`Unknown command: ${subcommand}`))\n p.note('Use --help to see available commands', 'Tip')\n process.exit(1)\n }\n\n process.exit(0)\n } catch (err: unknown) {\n // eslint-disable-next-line no-console\n console.error(err instanceof Error ? err.message : 'An error occurred')\n process.exit(1)\n }\n }\n}\n"],"names":["p","arg","pc","deployCommand","initCommand","listTokensCommand","loginCommand","logoutCommand","feedbackOutro","helpMessage","main","Main","init","e","Error","console","error","message","args","Boolean","String","permissive","process","env","DEBUG","exit","subcommand","_","log","intro","bgCyan","black","debug","yes","id","name","force","skipAuth","undefined","note","outro","red","err"],"mappings":"AAAA,YAAYA,OAAO,iBAAgB;AACnC,OAAOC,SAAS,MAAK;AACrB,OAAOC,QAAQ,aAAY;AAI3B,SAASC,aAAa,QAAQ,uBAAsB;AACpD,SAASC,WAAW,QAAQ,qBAAoB;AAChD,SAASC,iBAAiB,QAAQ,4BAA2B;AAC7D,SAASC,YAAY,QAAQ,sBAAqB;AAClD,SAASC,aAAa,QAAQ,uBAAsB;AACpD,SAASC,aAAa,EAAEC,WAAW,QAAQ,sBAAqB;AAEhE;;CAEC,GACD,OAAO,eAAeC;IACpB,IAAI;QACF,MAAM,IAAIC,OAAOC,IAAI;IACvB,EAAE,OAAOC,GAAG;QACV,IAAIA,aAAaC,OAAO;YACtB,sCAAsC;YACtCC,QAAQC,KAAK,CAACH,EAAEI,OAAO;QACzB;IACF;AACF;AAEA,MAAMN;IACJO,KAAa;IAEb,aAAc;QACZ,+BAA+B;QAC/B,IAAI,CAACA,IAAI,GAAGjB,IACV;YACE,WAAWkB;YACX,WAAWA;YACX,UAAUA;YACV,QAAQC;YACR,UAAUA;YACV,eAAeD;YACf,SAASA;YAET,UAAU;YACV,MAAM;YACN,MAAM;YACN,MAAM;QACR,GACA;YAAEE,YAAY;QAAK;QAGrB,0BAA0B;QAC1B,IAAI,IAAI,CAACH,IAAI,CAAC,UAAU,EAAE;YACxBI,QAAQC,GAAG,CAACC,KAAK,GAAG;QACtB;IACF;IAEA,MAAMZ,OAAsB;QAC1B,IAAI;YACF,IAAI,IAAI,CAACM,IAAI,CAAC,SAAS,EAAE;gBACvBT;gBACAa,QAAQG,IAAI,CAAC;YACf;YAEA,+CAA+C;YAC/C,MAAMC,aAAa,IAAI,CAACR,IAAI,CAACS,CAAC,CAAC,EAAE;YAEjC,sCAAsC;YACtCZ,QAAQa,GAAG,CAAC;YACZ5B,EAAE6B,KAAK,CAAC3B,GAAG4B,MAAM,CAAC5B,GAAG6B,KAAK,CAAC;YAE3B,uCAAuC;YACvC,OAAQL;gBACN,KAAK;oBACH,MAAMvB,cAAc;wBAClB6B,OAAO,IAAI,CAACd,IAAI,CAAC,UAAU;wBAC3Be,KAAK,IAAI,CAACf,IAAI,CAAC,QAAQ;oBACzB;oBACA;gBAEF,KAAK;oBACH,MAAMd,YAAY;wBAChB8B,IAAI,IAAI,CAAChB,IAAI,CAAC,OAAO;wBACrBiB,MAAM,IAAI,CAACjB,IAAI,CAAC,SAAS;wBACzBc,OAAO,IAAI,CAACd,IAAI,CAAC,UAAU;wBAC3BkB,OAAO,IAAI,CAAClB,IAAI,CAAC,UAAU;wBAC3BmB,UAAU,IAAI,CAACnB,IAAI,CAAC,cAAc;oBACpC;oBACA;gBAEF,KAAK;oBACHb,kBAAkB;wBAChB2B,OAAO,IAAI,CAACd,IAAI,CAAC,UAAU;oBAC7B;oBACA;gBAEF,KAAK;oBACH,MAAMZ;oBACN;gBAEF,KAAK;oBACH,MAAMC,cAAc;wBAClByB,OAAO,IAAI,CAACd,IAAI,CAAC,UAAU;oBAC7B;oBACA;gBAEF,KAAKoB;oBACH,uCAAuC;oBACvCtC,EAAEuC,IAAI,CAAC;oBACPvC,EAAEwC,KAAK,CAAChC;oBACR;gBAEF;oBACER,EAAE4B,GAAG,CAACZ,KAAK,CAACd,GAAGuC,GAAG,CAAC,CAAC,iBAAiB,EAAEf,YAAY;oBACnD1B,EAAEuC,IAAI,CAAC,wCAAwC;oBAC/CjB,QAAQG,IAAI,CAAC;YACjB;YAEAH,QAAQG,IAAI,CAAC;QACf,EAAE,OAAOiB,KAAc;YACrB,sCAAsC;YACtC3B,QAAQC,KAAK,CAAC0B,eAAe5B,QAAQ4B,IAAIzB,OAAO,GAAG;YACnDK,QAAQG,IAAI,CAAC;QACf;IACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAkBA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,wBAAwB;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gCAAgC;IAChC,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AA6BD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmThF"}
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAoBA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,wBAAwB;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gCAAgC;IAChC,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AA6BD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyThF"}
@@ -2,15 +2,17 @@ import * as p from '@clack/prompts';
2
2
  import { spawn } from 'child_process';
3
3
  import path from 'path';
4
4
  import pc from 'picocolors';
5
+ import { Project } from 'ts-morph';
5
6
  import { createDeployment, getTenantDetails, performDeployment } from '../api/control-plane.js';
6
7
  import { getValidAccessToken } from '../auth/oauth-flow.js';
7
8
  import { getValidProjectToken } from '../auth/project-token.js';
8
9
  import { TokenStore } from '../auth/token-store.js';
9
10
  import { collectStaticAssets, createLambdaZip, getFileSize } from '../utils/asset-collection.js';
10
11
  import { detectBuild, getBuildCommand } from '../utils/build-detection.js';
11
- import { hasFigmaConfig, readFigmaConfig } from '../utils/config.js';
12
12
  import * as log from '../utils/log.js';
13
13
  import { getPackageManager } from '../utils/package-manager.js';
14
+ import { readFigmaConfig } from '../utils/payload-config-ast.js';
15
+ import { findPayloadConfig } from '../utils/payload-config-finder.js';
14
16
  import { isInProjectDirectory } from '../utils/project.js';
15
17
  import { uploadLambdaZip, uploadStaticAssets } from '../utils/s3-upload.js';
16
18
  import { loginCommand } from './login.js';
@@ -57,16 +59,23 @@ import { loginCommand } from './login.js';
57
59
  p.note('Create a project or connect an existing one to Figma: npx @payloadcms/figma init', 'Tip');
58
60
  process.exit(1);
59
61
  }
60
- // Check if project connected to Figma
61
- if (!await hasFigmaConfig(projectPath)) {
62
- p.log.error(pc.red('✗ Your project is not connected to a Figma CMS ID.'));
62
+ // Find and read payload config
63
+ const configPath = await findPayloadConfig(projectPath);
64
+ if (!configPath) {
65
+ p.log.error(pc.red('✗ payload.config.ts not found'));
63
66
  p.note('Run npx @payloadcms/figma init to configure your project.', 'Tip');
64
67
  process.exit(1);
65
68
  }
66
- // Get tenant configuration
67
- const config = await readFigmaConfig(projectPath);
69
+ // Parse config with ts-morph
70
+ const project = new Project({
71
+ skipAddingFilesFromTsConfig: true
72
+ });
73
+ const sourceFile = project.addSourceFileAtPath(configPath);
74
+ // Read figma configuration from buildConfig
75
+ const config = readFigmaConfig(sourceFile);
68
76
  if (!config || !config.tenantId) {
69
- p.log.error(pc.red('✗ No tenant ID found in figma.config.json'));
77
+ p.log.error(pc.red('✗ No figma configuration found in payload.config.ts'));
78
+ p.note('Run npx @payloadcms/figma init to configure your project.', 'Tip');
70
79
  process.exit(1);
71
80
  }
72
81
  // Check authentication
@@ -74,9 +83,7 @@ import { loginCommand } from './login.js';
74
83
  let accessToken = await getValidAccessToken(tokenStore);
75
84
  if (!accessToken) {
76
85
  p.log.message('Please log in to continue');
77
- await loginCommand({
78
- debug: options.debug
79
- });
86
+ await loginCommand();
80
87
  accessToken = await getValidAccessToken(tokenStore);
81
88
  if (!accessToken) {
82
89
  p.log.error(pc.red('✗ Authentication failed'));
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/deploy.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport { spawn } from 'child_process'\nimport path from 'path'\nimport pc from 'picocolors'\n\nimport { createDeployment, getTenantDetails, performDeployment } from '../api/control-plane.js'\nimport { getValidAccessToken } from '../auth/oauth-flow.js'\nimport { getValidProjectToken } from '../auth/project-token.js'\nimport { TokenStore } from '../auth/token-store.js'\nimport { collectStaticAssets, createLambdaZip, getFileSize } from '../utils/asset-collection.js'\nimport { detectBuild, getBuildCommand } from '../utils/build-detection.js'\nimport { hasFigmaConfig, readFigmaConfig } from '../utils/config.js'\nimport * as log from '../utils/log.js'\nimport { getPackageManager } from '../utils/package-manager.js'\nimport { isInProjectDirectory } from '../utils/project.js'\nimport { uploadLambdaZip, uploadStaticAssets } from '../utils/s3-upload.js'\nimport { loginCommand } from './login.js'\n\n/**\n * Options for deploy command\n */\nexport interface DeployCommandOptions {\n /** Enable debug mode */\n debug?: boolean\n /** Skip confirmation prompts */\n yes?: boolean\n}\n\n/**\n * Format bytes to human-readable string\n */\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) {\n return '0 B'\n }\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`\n}\n\n/**\n * Format date to human-readable string in local time\n */\nfunction formatDate(date: Date): string {\n return date.toLocaleString('en-US', {\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n month: 'long',\n timeZoneName: 'short',\n year: 'numeric',\n })\n}\n\n/**\n * Execute the deploy command\n *\n * @param options - Command options\n */\nexport async function deployCommand(options: DeployCommandOptions): Promise<void> {\n const projectPath = process.cwd()\n const spinner = p.spinner()\n\n try {\n // ===== PRE-FLIGHT CHECKS =====\n\n // Check if in project directory\n if (!(await isInProjectDirectory(projectPath))) {\n p.log.error(pc.red(\"✗ 'deploy' command is not available outside of a Payload project.\"))\n p.note(\n 'Create a project or connect an existing one to Figma: npx @payloadcms/figma init',\n 'Tip',\n )\n process.exit(1)\n }\n\n // Check if project connected to Figma\n if (!(await hasFigmaConfig(projectPath))) {\n p.log.error(pc.red('✗ Your project is not connected to a Figma CMS ID.'))\n p.note('Run npx @payloadcms/figma init to configure your project.', 'Tip')\n process.exit(1)\n }\n\n // Get tenant configuration\n const config = await readFigmaConfig(projectPath)\n if (!config || !config.tenantId) {\n p.log.error(pc.red('✗ No tenant ID found in figma.config.json'))\n process.exit(1)\n }\n\n // Check authentication\n const tokenStore = new TokenStore()\n\n let accessToken = await getValidAccessToken(tokenStore)\n if (!accessToken) {\n p.log.message('Please log in to continue')\n await loginCommand({ debug: options.debug })\n accessToken = await getValidAccessToken(tokenStore)\n if (!accessToken) {\n p.log.error(pc.red('✗ Authentication failed'))\n process.exit(1)\n }\n }\n\n // Get project token\n try {\n await getValidProjectToken(tokenStore, config.tenantId)\n } catch (error) {\n p.log.error(pc.yellow('⚠ Project token invalid'))\n throw error\n }\n\n // ===== BUILD VALIDATION =====\n\n spinner.start('Checking for build...')\n let buildInfo = await detectBuild(projectPath)\n\n if (!buildInfo) {\n spinner.stop(pc.yellow('⚠ No build found for this project.'))\n\n // Try to find build command\n const buildCmd = await getBuildCommand(projectPath)\n\n if (!buildCmd) {\n p.log.error('No build script found in package.json')\n p.note('Add a build script to package.json: \"build\": \"next build\"', 'Tip')\n process.exit(1)\n }\n\n // Prompt to run build\n if (!options.yes) {\n const shouldBuild = await p.confirm({\n initialValue: true,\n message: `Build command found in package.json. Run it?`,\n })\n\n if (p.isCancel(shouldBuild) || !shouldBuild) {\n p.log.message('Cancelling deployment...')\n process.exit(0)\n }\n }\n\n // Run build\n const packageManager = await getPackageManager(projectPath)\n const buildCommand = `${packageManager} run build`\n spinner.stop(`Running ${buildCommand}...\\n`)\n\n try {\n // Stream build output to user with formatting\n const buildProcess = spawn(packageManager, ['run', 'build'], {\n cwd: projectPath,\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n // Indent and dim output\n buildProcess.stdout?.on('data', (data) => {\n const lines = data.toString().split('\\n')\n lines.forEach((line: string) => {\n if (line.trim()) {\n // eslint-disable-next-line no-console\n console.log(pc.dim(` ${line}`)) // Standard output\n }\n })\n })\n\n buildProcess.stderr?.on('data', (data) => {\n const lines = data.toString().split('\\n')\n lines.forEach((line: string) => {\n if (line.trim()) {\n // eslint-disable-next-line no-console\n console.log(pc.dim(` ${line}`)) // Standard error\n }\n })\n })\n\n const exitCode = await new Promise<number>((resolve) => {\n buildProcess.on('close', resolve)\n })\n\n if (exitCode !== 0) {\n throw new Error(`Build process exited with code ${exitCode}`)\n }\n\n p.log.success(pc.green('✓ Build completed'))\n } catch (error) {\n p.log.error(pc.red('✗ Build failed'))\n if (error instanceof Error && options.debug) {\n log.error(`Build error: ${error.message}`)\n }\n process.exit(1)\n }\n\n // Re-check for build\n buildInfo = await detectBuild(projectPath)\n if (!buildInfo) {\n p.log.error(pc.red('✗ Build completed but standalone build not found'))\n p.note('Ensure next.config.js has output: \"standalone\"', 'Check Lambda Configuration')\n process.exit(1)\n }\n } else {\n spinner.stop(pc.green('✓ Build found'))\n p.note(\n [\n `${pc.cyan('Build ID:')} ${buildInfo.buildId}`,\n `${pc.cyan('Date:')} ${formatDate(buildInfo.timestamp)}`,\n ].join('\\n'),\n 'Build Details',\n )\n }\n\n // ===== DEPLOYMENT PREPARATION =====\n\n // Create Lambda zip\n spinner.start('Creating deployment package...')\n try {\n await createLambdaZip(projectPath)\n spinner.stop(pc.green('✓ Deployment package created'))\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to create deployment package'))\n throw error\n }\n\n // Collect static assets\n spinner.start('Collecting static assets...')\n const staticAssets = await collectStaticAssets(projectPath)\n const zipPath = path.join(projectPath, 'lambda.zip')\n const zipSize = await getFileSize(zipPath)\n spinner.stop(pc.green(`✓ ${staticAssets.length} static assets detected`))\n\n log.debug(`Lambda zip size: ${formatBytes(zipSize)}`)\n log.debug(`Static assets: ${staticAssets.length} files`)\n\n // ===== DEPLOYMENT CONFIRMATION =====\n\n if (!options.yes) {\n p.note(\n [\n `${pc.cyan('Build ID:')} ${buildInfo.buildId}`,\n `${pc.cyan('Date:')} ${formatDate(buildInfo.timestamp)}`,\n `${pc.cyan('Code size:')} ${formatBytes(zipSize)}`,\n `${pc.cyan('Static assets:')} ${staticAssets.length} files`,\n ].join('\\n'),\n 'Details',\n )\n\n const shouldDeploy = await p.confirm({\n initialValue: true,\n message: 'Deploy this build to Figma?',\n })\n\n if (p.isCancel(shouldDeploy) || !shouldDeploy) {\n p.log.message('Cancelling deployment...')\n process.exit(0)\n }\n }\n\n // ===== DEPLOYMENT EXECUTION =====\n\n // Step 1: Create deployment\n spinner.start('Creating deployment...')\n let deploymentId: string\n let codeUploadUrl: string\n let staticAssetUploadUrls: Record<string, string>\n\n try {\n const createResponse = await createDeployment(accessToken, config.tenantId, {\n staticAssets,\n })\n\n deploymentId = createResponse.deploymentId\n codeUploadUrl = createResponse.codeUploadUrl\n staticAssetUploadUrls = createResponse.staticAssetUploadUrls\n\n log.debug(`Deployment ID: ${deploymentId}`)\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to create deployment'))\n throw error\n }\n\n // Step 2: Upload code\n spinner.message(`Uploading code (${formatBytes(zipSize)})...`)\n try {\n await uploadLambdaZip(zipPath, codeUploadUrl)\n spinner.stop(pc.green(`✓ Code uploaded (${formatBytes(zipSize)})`))\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to upload code'))\n throw error\n }\n\n // Step 3: Upload static assets\n if (staticAssets.length > 0) {\n spinner.start('Uploading static assets...')\n\n try {\n const uploadResults = await uploadStaticAssets(\n projectPath,\n staticAssetUploadUrls,\n (uploaded, total) => {\n spinner.message(`Uploading static assets (${uploaded}/${total})...`)\n },\n )\n\n if (uploadResults.assetsFailed > 0) {\n spinner.stop(\n pc.yellow(\n `⚠ ${uploadResults.assetsUploaded}/${staticAssets.length} assets uploaded (${uploadResults.assetsFailed} failed)`,\n ),\n )\n p.log.warning(\n `${uploadResults.assetsFailed} assets failed to upload. Deployment may be incomplete.`,\n )\n } else {\n spinner.stop(\n pc.green(\n `✓ Static assets uploaded (${uploadResults.assetsUploaded} files, ${formatBytes(uploadResults.totalBytesUploaded)})`,\n ),\n )\n }\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to upload assets'))\n throw error\n }\n }\n\n // Step 4: Perform deployment\n spinner.start('Performing deployment...')\n try {\n await performDeployment(accessToken, config.tenantId, {\n deploymentId,\n })\n spinner.stop(pc.green('✓ Deployment initiated'))\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to perform deployment'))\n throw error\n }\n\n // TODO: Add deployment progress tracking\n // Future: Poll deployment status and show progress\n // API endpoint: GET /v1/tenant/{tenant_id}/deploy/{deployment_id}/status\n\n // Success output\n p.log.message('This usually takes 2-3 minutes to complete.')\n\n // Get tenant details for URL\n try {\n const tenant = await getTenantDetails(accessToken, config.tenantId)\n if (tenant.domain) {\n p.log.message(`View: ${pc.cyan(`https://${tenant.domain}/`)}`)\n }\n } catch {\n // Non-critical - just skip URL display\n }\n\n p.note(\n `Manage your deployment at:\\n${pc.cyan(`https://cms.figma.com/manage/tenants/${config.tenantId}`)}`,\n 'Next Steps',\n )\n } catch (error) {\n spinner.stop(pc.red('✗ Failed'))\n const message = error instanceof Error ? error.message : 'Unknown error'\n p.log.error(pc.red(`✗ ${message}`))\n if (options.debug && error instanceof Error && error.stack) {\n log.error(`Stack trace: ${error.stack}`)\n }\n process.exit(1)\n }\n}\n"],"names":["p","spawn","path","pc","createDeployment","getTenantDetails","performDeployment","getValidAccessToken","getValidProjectToken","TokenStore","collectStaticAssets","createLambdaZip","getFileSize","detectBuild","getBuildCommand","hasFigmaConfig","readFigmaConfig","log","getPackageManager","isInProjectDirectory","uploadLambdaZip","uploadStaticAssets","loginCommand","formatBytes","bytes","k","sizes","i","Math","floor","parseFloat","pow","toFixed","formatDate","date","toLocaleString","day","hour","minute","month","timeZoneName","year","deployCommand","options","projectPath","process","cwd","spinner","error","red","note","exit","config","tenantId","tokenStore","accessToken","message","debug","yellow","start","buildInfo","stop","buildCmd","yes","shouldBuild","confirm","initialValue","isCancel","packageManager","buildCommand","buildProcess","stdio","stdout","on","data","lines","toString","split","forEach","line","trim","console","dim","stderr","exitCode","Promise","resolve","Error","success","green","cyan","buildId","timestamp","join","staticAssets","zipPath","zipSize","length","shouldDeploy","deploymentId","codeUploadUrl","staticAssetUploadUrls","createResponse","uploadResults","uploaded","total","assetsFailed","assetsUploaded","warning","totalBytesUploaded","tenant","domain","stack"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/deploy.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport { spawn } from 'child_process'\nimport path from 'path'\nimport pc from 'picocolors'\nimport { Project } from 'ts-morph'\n\nimport { createDeployment, getTenantDetails, performDeployment } from '../api/control-plane.js'\nimport { getValidAccessToken } from '../auth/oauth-flow.js'\nimport { getValidProjectToken } from '../auth/project-token.js'\nimport { TokenStore } from '../auth/token-store.js'\nimport { collectStaticAssets, createLambdaZip, getFileSize } from '../utils/asset-collection.js'\nimport { detectBuild, getBuildCommand } from '../utils/build-detection.js'\nimport * as log from '../utils/log.js'\nimport { getPackageManager } from '../utils/package-manager.js'\nimport { readFigmaConfig } from '../utils/payload-config-ast.js'\nimport { findPayloadConfig } from '../utils/payload-config-finder.js'\nimport { isInProjectDirectory } from '../utils/project.js'\nimport { uploadLambdaZip, uploadStaticAssets } from '../utils/s3-upload.js'\nimport { loginCommand } from './login.js'\n\n/**\n * Options for deploy command\n */\nexport interface DeployCommandOptions {\n /** Enable debug mode */\n debug?: boolean\n /** Skip confirmation prompts */\n yes?: boolean\n}\n\n/**\n * Format bytes to human-readable string\n */\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) {\n return '0 B'\n }\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`\n}\n\n/**\n * Format date to human-readable string in local time\n */\nfunction formatDate(date: Date): string {\n return date.toLocaleString('en-US', {\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n month: 'long',\n timeZoneName: 'short',\n year: 'numeric',\n })\n}\n\n/**\n * Execute the deploy command\n *\n * @param options - Command options\n */\nexport async function deployCommand(options: DeployCommandOptions): Promise<void> {\n const projectPath = process.cwd()\n const spinner = p.spinner()\n\n try {\n // ===== PRE-FLIGHT CHECKS =====\n\n // Check if in project directory\n if (!(await isInProjectDirectory(projectPath))) {\n p.log.error(pc.red(\"✗ 'deploy' command is not available outside of a Payload project.\"))\n p.note(\n 'Create a project or connect an existing one to Figma: npx @payloadcms/figma init',\n 'Tip',\n )\n process.exit(1)\n }\n\n // Find and read payload config\n const configPath = await findPayloadConfig(projectPath)\n if (!configPath) {\n p.log.error(pc.red('✗ payload.config.ts not found'))\n p.note('Run npx @payloadcms/figma init to configure your project.', 'Tip')\n process.exit(1)\n }\n\n // Parse config with ts-morph\n const project = new Project({ skipAddingFilesFromTsConfig: true })\n const sourceFile = project.addSourceFileAtPath(configPath)\n\n // Read figma configuration from buildConfig\n const config = readFigmaConfig(sourceFile)\n if (!config || !config.tenantId) {\n p.log.error(pc.red('✗ No figma configuration found in payload.config.ts'))\n p.note('Run npx @payloadcms/figma init to configure your project.', 'Tip')\n process.exit(1)\n }\n\n // Check authentication\n const tokenStore = new TokenStore()\n\n let accessToken = await getValidAccessToken(tokenStore)\n if (!accessToken) {\n p.log.message('Please log in to continue')\n await loginCommand()\n accessToken = await getValidAccessToken(tokenStore)\n if (!accessToken) {\n p.log.error(pc.red('✗ Authentication failed'))\n process.exit(1)\n }\n }\n\n // Get project token\n try {\n await getValidProjectToken(tokenStore, config.tenantId)\n } catch (error) {\n p.log.error(pc.yellow('⚠ Project token invalid'))\n throw error\n }\n\n // ===== BUILD VALIDATION =====\n\n spinner.start('Checking for build...')\n let buildInfo = await detectBuild(projectPath)\n\n if (!buildInfo) {\n spinner.stop(pc.yellow('⚠ No build found for this project.'))\n\n // Try to find build command\n const buildCmd = await getBuildCommand(projectPath)\n\n if (!buildCmd) {\n p.log.error('No build script found in package.json')\n p.note('Add a build script to package.json: \"build\": \"next build\"', 'Tip')\n process.exit(1)\n }\n\n // Prompt to run build\n if (!options.yes) {\n const shouldBuild = await p.confirm({\n initialValue: true,\n message: `Build command found in package.json. Run it?`,\n })\n\n if (p.isCancel(shouldBuild) || !shouldBuild) {\n p.log.message('Cancelling deployment...')\n process.exit(0)\n }\n }\n\n // Run build\n const packageManager = await getPackageManager(projectPath)\n const buildCommand = `${packageManager} run build`\n spinner.stop(`Running ${buildCommand}...\\n`)\n\n try {\n // Stream build output to user with formatting\n const buildProcess = spawn(packageManager, ['run', 'build'], {\n cwd: projectPath,\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n // Indent and dim output\n buildProcess.stdout?.on('data', (data) => {\n const lines = data.toString().split('\\n')\n lines.forEach((line: string) => {\n if (line.trim()) {\n // eslint-disable-next-line no-console\n console.log(pc.dim(` ${line}`)) // Standard output\n }\n })\n })\n\n buildProcess.stderr?.on('data', (data) => {\n const lines = data.toString().split('\\n')\n lines.forEach((line: string) => {\n if (line.trim()) {\n // eslint-disable-next-line no-console\n console.log(pc.dim(` ${line}`)) // Standard error\n }\n })\n })\n\n const exitCode = await new Promise<number>((resolve) => {\n buildProcess.on('close', resolve)\n })\n\n if (exitCode !== 0) {\n throw new Error(`Build process exited with code ${exitCode}`)\n }\n\n p.log.success(pc.green('✓ Build completed'))\n } catch (error) {\n p.log.error(pc.red('✗ Build failed'))\n if (error instanceof Error && options.debug) {\n log.error(`Build error: ${error.message}`)\n }\n process.exit(1)\n }\n\n // Re-check for build\n buildInfo = await detectBuild(projectPath)\n if (!buildInfo) {\n p.log.error(pc.red('✗ Build completed but standalone build not found'))\n p.note('Ensure next.config.js has output: \"standalone\"', 'Check Lambda Configuration')\n process.exit(1)\n }\n } else {\n spinner.stop(pc.green('✓ Build found'))\n p.note(\n [\n `${pc.cyan('Build ID:')} ${buildInfo.buildId}`,\n `${pc.cyan('Date:')} ${formatDate(buildInfo.timestamp)}`,\n ].join('\\n'),\n 'Build Details',\n )\n }\n\n // ===== DEPLOYMENT PREPARATION =====\n\n // Create Lambda zip\n spinner.start('Creating deployment package...')\n try {\n await createLambdaZip(projectPath)\n spinner.stop(pc.green('✓ Deployment package created'))\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to create deployment package'))\n throw error\n }\n\n // Collect static assets\n spinner.start('Collecting static assets...')\n const staticAssets = await collectStaticAssets(projectPath)\n const zipPath = path.join(projectPath, 'lambda.zip')\n const zipSize = await getFileSize(zipPath)\n spinner.stop(pc.green(`✓ ${staticAssets.length} static assets detected`))\n\n log.debug(`Lambda zip size: ${formatBytes(zipSize)}`)\n log.debug(`Static assets: ${staticAssets.length} files`)\n\n // ===== DEPLOYMENT CONFIRMATION =====\n\n if (!options.yes) {\n p.note(\n [\n `${pc.cyan('Build ID:')} ${buildInfo.buildId}`,\n `${pc.cyan('Date:')} ${formatDate(buildInfo.timestamp)}`,\n `${pc.cyan('Code size:')} ${formatBytes(zipSize)}`,\n `${pc.cyan('Static assets:')} ${staticAssets.length} files`,\n ].join('\\n'),\n 'Details',\n )\n\n const shouldDeploy = await p.confirm({\n initialValue: true,\n message: 'Deploy this build to Figma?',\n })\n\n if (p.isCancel(shouldDeploy) || !shouldDeploy) {\n p.log.message('Cancelling deployment...')\n process.exit(0)\n }\n }\n\n // ===== DEPLOYMENT EXECUTION =====\n\n // Step 1: Create deployment\n spinner.start('Creating deployment...')\n let deploymentId: string\n let codeUploadUrl: string\n let staticAssetUploadUrls: Record<string, string>\n\n try {\n const createResponse = await createDeployment(accessToken, config.tenantId, {\n staticAssets,\n })\n\n deploymentId = createResponse.deploymentId\n codeUploadUrl = createResponse.codeUploadUrl\n staticAssetUploadUrls = createResponse.staticAssetUploadUrls\n\n log.debug(`Deployment ID: ${deploymentId}`)\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to create deployment'))\n throw error\n }\n\n // Step 2: Upload code\n spinner.message(`Uploading code (${formatBytes(zipSize)})...`)\n try {\n await uploadLambdaZip(zipPath, codeUploadUrl)\n spinner.stop(pc.green(`✓ Code uploaded (${formatBytes(zipSize)})`))\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to upload code'))\n throw error\n }\n\n // Step 3: Upload static assets\n if (staticAssets.length > 0) {\n spinner.start('Uploading static assets...')\n\n try {\n const uploadResults = await uploadStaticAssets(\n projectPath,\n staticAssetUploadUrls,\n (uploaded, total) => {\n spinner.message(`Uploading static assets (${uploaded}/${total})...`)\n },\n )\n\n if (uploadResults.assetsFailed > 0) {\n spinner.stop(\n pc.yellow(\n `⚠ ${uploadResults.assetsUploaded}/${staticAssets.length} assets uploaded (${uploadResults.assetsFailed} failed)`,\n ),\n )\n p.log.warning(\n `${uploadResults.assetsFailed} assets failed to upload. Deployment may be incomplete.`,\n )\n } else {\n spinner.stop(\n pc.green(\n `✓ Static assets uploaded (${uploadResults.assetsUploaded} files, ${formatBytes(uploadResults.totalBytesUploaded)})`,\n ),\n )\n }\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to upload assets'))\n throw error\n }\n }\n\n // Step 4: Perform deployment\n spinner.start('Performing deployment...')\n try {\n await performDeployment(accessToken, config.tenantId, {\n deploymentId,\n })\n spinner.stop(pc.green('✓ Deployment initiated'))\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to perform deployment'))\n throw error\n }\n\n // TODO: Add deployment progress tracking\n // Future: Poll deployment status and show progress\n // API endpoint: GET /v1/tenant/{tenant_id}/deploy/{deployment_id}/status\n\n // Success output\n p.log.message('This usually takes 2-3 minutes to complete.')\n\n // Get tenant details for URL\n try {\n const tenant = await getTenantDetails(accessToken, config.tenantId)\n if (tenant.domain) {\n p.log.message(`View: ${pc.cyan(`https://${tenant.domain}/`)}`)\n }\n } catch {\n // Non-critical - just skip URL display\n }\n\n p.note(\n `Manage your deployment at:\\n${pc.cyan(`https://cms.figma.com/manage/tenants/${config.tenantId}`)}`,\n 'Next Steps',\n )\n } catch (error) {\n spinner.stop(pc.red('✗ Failed'))\n const message = error instanceof Error ? error.message : 'Unknown error'\n p.log.error(pc.red(`✗ ${message}`))\n if (options.debug && error instanceof Error && error.stack) {\n log.error(`Stack trace: ${error.stack}`)\n }\n process.exit(1)\n }\n}\n"],"names":["p","spawn","path","pc","Project","createDeployment","getTenantDetails","performDeployment","getValidAccessToken","getValidProjectToken","TokenStore","collectStaticAssets","createLambdaZip","getFileSize","detectBuild","getBuildCommand","log","getPackageManager","readFigmaConfig","findPayloadConfig","isInProjectDirectory","uploadLambdaZip","uploadStaticAssets","loginCommand","formatBytes","bytes","k","sizes","i","Math","floor","parseFloat","pow","toFixed","formatDate","date","toLocaleString","day","hour","minute","month","timeZoneName","year","deployCommand","options","projectPath","process","cwd","spinner","error","red","note","exit","configPath","project","skipAddingFilesFromTsConfig","sourceFile","addSourceFileAtPath","config","tenantId","tokenStore","accessToken","message","yellow","start","buildInfo","stop","buildCmd","yes","shouldBuild","confirm","initialValue","isCancel","packageManager","buildCommand","buildProcess","stdio","stdout","on","data","lines","toString","split","forEach","line","trim","console","dim","stderr","exitCode","Promise","resolve","Error","success","green","debug","cyan","buildId","timestamp","join","staticAssets","zipPath","zipSize","length","shouldDeploy","deploymentId","codeUploadUrl","staticAssetUploadUrls","createResponse","uploadResults","uploaded","total","assetsFailed","assetsUploaded","warning","totalBytesUploaded","tenant","domain","stack"],"mappings":"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"}
@@ -10,6 +10,10 @@ export interface InitCommandOptions {
10
10
  id?: string;
11
11
  /** Project name (for scaffolding) */
12
12
  name?: string;
13
+ /** Disable Content System (defaults to enabled) */
14
+ noContentSystem?: boolean;
15
+ /** AWS region for deployment (defaults to us-east-1) */
16
+ region?: string;
13
17
  /** Skip authentication check (for testing/development) */
14
18
  skipAuth?: boolean;
15
19
  /** Skip prompts and use defaults where possible */
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AA6BA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,wBAAwB;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mDAAmD;IACnD,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AAiDD;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2a5E"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AA6BA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,wBAAwB;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,mDAAmD;IACnD,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mDAAmD;IACnD,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AAiDD;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmW5E"}
@@ -3,10 +3,10 @@ import fs from 'fs/promises';
3
3
  import path from 'path';
4
4
  import pc from 'picocolors';
5
5
  import { ControlPlaneError, getTenantDetails } from '../api/control-plane.js';
6
+ import { FigmaApiError } from '../api/figma-api.js';
6
7
  import { getValidAccessToken } from '../auth/oauth-flow.js';
7
8
  import { getValidProjectToken, ProjectTokenError } from '../auth/project-token.js';
8
9
  import { TokenStore } from '../auth/token-store.js';
9
- import { hasFigmaConfig, readFigmaConfig, writeFigmaConfig } from '../utils/config.js';
10
10
  import { isDebug } from '../utils/is-debug.js';
11
11
  import * as log from '../utils/log.js';
12
12
  import { displayManualInstructions, ensurePayloadFigmaConfig } from '../utils/payload-config-modifier.js';
@@ -34,17 +34,15 @@ import { loginCommand } from './login.js';
34
34
  }
35
35
  }
36
36
  } catch (error) {
37
- // Always show failures, even without debug
38
37
  if (isDebug()) {
39
38
  spinner.stop(pc.yellow('⚠ Project token generation failed'));
40
39
  }
41
- if (error instanceof ProjectTokenError) {
40
+ // Always show failures, even without debug
41
+ if (error instanceof ProjectTokenError || error instanceof FigmaApiError) {
42
42
  log.warning(error.message);
43
- if (isDebug()) {
44
- p.note('Project token is used for authenticating to the Content API.\nYou can continue without it, but may need to regenerate later.', 'Note');
45
- }
43
+ p.note('Project token is used for authenticating to the Content API.\nYou can continue without it, but may need to regenerate later.', 'Note');
46
44
  } else {
47
- log.warning(error instanceof Error ? error.message : 'Unknown error');
45
+ log.warning(`Unable to retrieve project token: ${error instanceof Error ? error.message : 'Unknown error'}`);
48
46
  }
49
47
  // Don't exit - token generation failure shouldn't block initialization
50
48
  }
@@ -112,34 +110,9 @@ import { loginCommand } from './login.js';
112
110
  process.exit(1);
113
111
  }
114
112
  }
115
- // Check if already initialized
116
- const hasConfig = await hasFigmaConfig();
117
- if (hasConfig && !options.force) {
118
- // Read existing config
119
- const config = await readFigmaConfig();
120
- if (!config) {
121
- p.log.error('Failed to read existing configuration');
122
- process.exit(1);
123
- }
124
- // Display existing CMS details
125
- p.log.info(pc.bold('Project already initialized'));
126
- const details = [
127
- `Tenant ID: ${config.tenantId}`,
128
- `Domain: ${pc.cyan(`https://${config.domain}`)}`
129
- ];
130
- // Optionally fetch live status from Control Plane
131
- if (!options.skipAuth) {
132
- try {
133
- const tenant = await getTenantDetails(accessToken, config.tenantId);
134
- details.push(`Status: ${tenant.status}`);
135
- } catch {
136
- // Ignore errors, just skip live status
137
- }
138
- }
139
- p.note(details.join('\n'), 'CMS Configuration');
140
- p.note('Use --force to reconfigure this project', 'Tip');
141
- process.exit(0);
142
- }
113
+ // Note: We no longer check for figma.config.json here
114
+ // Instead, the AST detection will check if figma object already exists in payload.config.ts
115
+ // and skip modification if it does (unless --force is used)
143
116
  // Step 3: Get CMS ID with retry loop
144
117
  log.debug('Configuring Project...');
145
118
  let tenantId = options.id;
@@ -192,7 +165,6 @@ import { loginCommand } from './login.js';
192
165
  }
193
166
  }
194
167
  // Step 4: Detect or scaffold Payload project
195
- // p.log.step(pc.bold('Setting up project...'))
196
168
  const isInProject = await isInProjectDirectory();
197
169
  if (isInProject) {
198
170
  // ===== EXISTING PROJECT FLOW =====
@@ -223,7 +195,11 @@ import { loginCommand } from './login.js';
223
195
  }
224
196
  }
225
197
  s.start('Checking Payload configuration...');
226
- const modResult = await ensurePayloadFigmaConfig(process.cwd(), projectInfo.packageManager || 'pnpm');
198
+ const modResult = await ensurePayloadFigmaConfig(process.cwd(), projectInfo.packageManager || 'pnpm', {
199
+ region: options.region || 'us-east-1',
200
+ tenantId: selectedTenant.id,
201
+ useContentSystem: !options.noContentSystem
202
+ });
227
203
  if (!modResult.success) {
228
204
  s.stop(pc.red('✗ Configuration check failed'));
229
205
  displayManualInstructions(modResult.error || 'Unknown error');
@@ -232,7 +208,7 @@ import { loginCommand } from './login.js';
232
208
  if (modResult.modified) {
233
209
  s.stop(pc.green('✓ Payload configuration updated'));
234
210
  if (modResult.changes.length > 0) {
235
- modResult.changes.forEach((change)=>log.info(pc.dim(` → ${change}`)));
211
+ modResult.changes.forEach((change)=>log.debug(pc.dim(` → ${change}`)));
236
212
  }
237
213
  } else {
238
214
  s.stop(pc.green('✓ Payload configuration valid'));
@@ -263,28 +239,6 @@ import { loginCommand } from './login.js';
263
239
  p.note('Create a new project or manually add Payload dependencies', 'Action Required');
264
240
  process.exit(1);
265
241
  }
266
- // Write configuration for existing project
267
- if (isDebug()) {
268
- s.start('Configuring your project...');
269
- }
270
- try {
271
- await writeFigmaConfig({
272
- domain: selectedTenant.domain,
273
- tenantId: selectedTenant.id
274
- });
275
- if (isDebug()) {
276
- s.stop(pc.green('✓ Project configured'));
277
- }
278
- } catch (error) {
279
- // Always show failures
280
- if (isDebug()) {
281
- s.stop(pc.red('✗ Failed'));
282
- } else {
283
- log.error('Failed to configure project');
284
- }
285
- log.error(error instanceof Error ? error.message : 'Unknown error');
286
- process.exit(1);
287
- }
288
242
  // Generate project token (unless skipping auth)
289
243
  if (!options.skipAuth) {
290
244
  await generateProjectTokenWithFeedback(tokenStore, selectedTenant.id, s);
@@ -292,7 +246,7 @@ import { loginCommand } from './login.js';
292
246
  // Success message for existing project
293
247
  p.outro(pc.green('✓ Project initialized successfully!'));
294
248
  const nextSteps = [
295
- selectedTenant.status === 'provisioning' ? 'Wait for CMS provisioning to complete (check status with `payloadcms-figma list`)' : undefined,
249
+ selectedTenant.status === 'provisioning' ? 'Wait for CMS provisioning to complete (check status with `@payloadcms/figma list`)' : undefined,
296
250
  'Start development server: `pnpm dev`',
297
251
  `Access your CMS at: ${pc.cyan(`https://${selectedTenant.domain}`)}`
298
252
  ].filter(Boolean);
@@ -345,7 +299,11 @@ import { loginCommand } from './login.js';
345
299
  }
346
300
  // Modify Payload configuration
347
301
  s.start('Checking Payload configuration...');
348
- const modResult = await ensurePayloadFigmaConfig(fullPath, 'pnpm');
302
+ const modResult = await ensurePayloadFigmaConfig(fullPath, 'pnpm', {
303
+ region: options.region || 'us-east-1',
304
+ tenantId: selectedTenant.id,
305
+ useContentSystem: !options.noContentSystem
306
+ });
349
307
  if (!modResult.success) {
350
308
  s.stop(pc.red('✗ Configuration check failed'));
351
309
  displayManualInstructions(modResult.error || 'Unknown error');
@@ -354,7 +312,7 @@ import { loginCommand } from './login.js';
354
312
  if (modResult.modified) {
355
313
  s.stop(pc.green('✓ Payload configuration updated'));
356
314
  if (modResult.changes.length > 0) {
357
- modResult.changes.forEach((change)=>log.info(pc.dim(` → ${change}`)));
315
+ modResult.changes.forEach((change)=>log.debug(pc.dim(` → ${change}`)));
358
316
  }
359
317
  } else {
360
318
  s.stop(pc.green('✓ Payload configuration valid'));
@@ -365,28 +323,6 @@ import { loginCommand } from './login.js';
365
323
  p.log.warn(pc.yellow(`⚠ ${warning}`));
366
324
  });
367
325
  }
368
- // Write configuration to new project directory
369
- if (isDebug()) {
370
- s.start('Configuring your project...');
371
- }
372
- try {
373
- await writeFigmaConfig({
374
- domain: selectedTenant.domain,
375
- tenantId: selectedTenant.id
376
- }, fullPath);
377
- if (isDebug()) {
378
- s.stop(pc.green('✓ Project configured'));
379
- }
380
- } catch (error) {
381
- // Always show failures
382
- if (isDebug()) {
383
- s.stop(pc.red('✗ Failed'));
384
- } else {
385
- log.error('Failed to configure project');
386
- }
387
- log.error(error instanceof Error ? error.message : 'Unknown error');
388
- process.exit(1);
389
- }
390
326
  // Generate project token (unless skipping auth)
391
327
  if (!options.skipAuth) {
392
328
  await generateProjectTokenWithFeedback(tokenStore, selectedTenant.id, s);