@payloadcms/figma 0.0.1-alpha.5 → 0.0.1-alpha.51

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 (326) hide show
  1. package/dist/api/control-plane.d.ts +31 -1
  2. package/dist/api/control-plane.js +137 -67
  3. package/dist/api/figma-api.d.ts +20 -0
  4. package/dist/api/figma-api.js +77 -21
  5. package/dist/auth/callback-server.js +2 -1
  6. package/dist/auth/crypto-utils.js +5 -5
  7. package/dist/auth/jwt-validator.d.ts +2 -1
  8. package/dist/auth/jwt-validator.js +2 -2
  9. package/dist/auth/oauth-flow.d.ts +1 -1
  10. package/dist/auth/oauth-flow.js +15 -11
  11. package/dist/auth/project-token.js +11 -6
  12. package/dist/auth/refresh.d.ts +2 -1
  13. package/dist/auth/refresh.js +25 -12
  14. package/dist/auth/token-store.d.ts +40 -1
  15. package/dist/auth/token-store.js +65 -5
  16. package/dist/auth/types.d.ts +17 -4
  17. package/dist/cli.js +54 -6
  18. package/dist/commands/build-lambda-zip.d.ts +5 -0
  19. package/dist/commands/build-lambda-zip.js +19 -0
  20. package/dist/commands/debug.d.ts +8 -0
  21. package/dist/commands/debug.js +161 -0
  22. package/dist/commands/deploy.d.ts +6 -0
  23. package/dist/commands/deploy.js +94 -126
  24. package/dist/commands/env.d.ts +13 -0
  25. package/dist/commands/env.js +88 -0
  26. package/dist/commands/init.d.ts +3 -5
  27. package/dist/commands/init.js +118 -94
  28. package/dist/commands/list-tokens.d.ts +3 -3
  29. package/dist/commands/list-tokens.js +22 -7
  30. package/dist/commands/login.d.ts +8 -1
  31. package/dist/commands/login.js +30 -12
  32. package/dist/commands/logout.d.ts +5 -4
  33. package/dist/commands/logout.js +56 -13
  34. package/dist/config/oauth.d.ts +4 -14
  35. package/dist/config/oauth.js +18 -40
  36. package/dist/constants.d.ts +36 -19
  37. package/dist/constants.js +58 -20
  38. package/dist/db-content-api/README.md +98 -0
  39. package/dist/db-content-api/generated/content-api-types.d.ts +3746 -0
  40. package/dist/db-content-api/generated/content-api-types.js +7 -0
  41. package/dist/db-content-api/index.d.ts +20 -0
  42. package/dist/db-content-api/index.js +702 -0
  43. package/dist/db-content-api/temp-utilities/slug.d.ts +2 -0
  44. package/dist/db-content-api/temp-utilities/slug.js +3 -0
  45. package/dist/db-content-api/temp-utilities/sorting.d.ts +3 -0
  46. package/dist/db-content-api/temp-utilities/sorting.js +32 -0
  47. package/dist/db-content-api/temp-utilities/types.d.ts +22 -0
  48. package/dist/db-content-api/temp-utilities/types.js +15 -0
  49. package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts +34 -0
  50. package/dist/db-content-api/temp-utilities/unwrapDocument.js +53 -0
  51. package/dist/db-content-api/utilities/auth.d.ts +30 -0
  52. package/dist/db-content-api/utilities/auth.js +81 -0
  53. package/dist/db-content-api/utilities/data/applyDefaults.d.ts +7 -0
  54. package/dist/db-content-api/utilities/data/applyDefaults.js +59 -0
  55. package/dist/db-content-api/utilities/data/castFieldValue.d.ts +11 -0
  56. package/dist/db-content-api/utilities/data/castFieldValue.js +69 -0
  57. package/dist/db-content-api/utilities/data/index.d.ts +42 -0
  58. package/dist/db-content-api/utilities/data/index.js +211 -0
  59. package/dist/db-content-api/utilities/data/removeVirtualFields.d.ts +12 -0
  60. package/dist/db-content-api/utilities/data/removeVirtualFields.js +54 -0
  61. package/dist/db-content-api/utilities/data/stripFields.d.ts +48 -0
  62. package/dist/db-content-api/utilities/data/stripFields.js +195 -0
  63. package/dist/db-content-api/utilities/data/transformPublishedLocale.d.ts +23 -0
  64. package/dist/db-content-api/utilities/data/transformPublishedLocale.js +42 -0
  65. package/dist/db-content-api/utilities/joins.d.ts +55 -0
  66. package/dist/db-content-api/utilities/joins.js +136 -0
  67. package/dist/db-content-api/utilities/locale/index.d.ts +10 -0
  68. package/dist/db-content-api/utilities/locale/index.js +21 -0
  69. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.d.ts +11 -0
  70. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js +66 -0
  71. package/dist/db-content-api/utilities/meta/buildMeta.d.ts +37 -0
  72. package/dist/db-content-api/utilities/meta/buildMeta.js +33 -0
  73. package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts +13 -0
  74. package/dist/db-content-api/utilities/meta/buildPathTypes.js +181 -0
  75. package/dist/db-content-api/utilities/where.d.ts +20 -0
  76. package/dist/db-content-api/utilities/where.js +127 -0
  77. package/dist/endpoints/health.d.ts +3 -0
  78. package/dist/endpoints/health.js +11 -0
  79. package/dist/endpoints/schema.d.ts +3 -0
  80. package/dist/endpoints/schema.js +29 -0
  81. package/dist/exports/client.d.ts +3 -0
  82. package/dist/exports/client.js +3 -0
  83. package/dist/index.d.ts +2 -1
  84. package/dist/index.js +3 -1
  85. package/dist/oauth/components/FigmaAvatar/index.d.ts +4 -0
  86. package/dist/oauth/components/FigmaAvatar/index.js +27 -0
  87. package/dist/oauth/components/FigmaAvatar/index.scss +12 -0
  88. package/dist/oauth/components/FigmaAvatarCell/index.d.ts +5 -0
  89. package/dist/oauth/components/FigmaAvatarCell/index.js +25 -0
  90. package/dist/oauth/components/FigmaAvatarCell/index.scss +5 -0
  91. package/dist/oauth/components/FigmaAvatarPlaceholder/index.d.ts +9 -0
  92. package/dist/oauth/components/FigmaAvatarPlaceholder/index.js +37 -0
  93. package/dist/oauth/components/FigmaAvatarPlaceholder/index.scss +28 -0
  94. package/dist/oauth/components/LoginButton/index.js +50 -6
  95. package/dist/oauth/components/LoginButton/index.scss +50 -3
  96. package/dist/oauth/components/LogoutButton/index.js +5 -4
  97. package/dist/oauth/defaults.js +67 -10
  98. package/dist/oauth/endpoints/getLoginEndpoint.js +69 -24
  99. package/dist/oauth/endpoints/getLogoutEndpoint.js +7 -4
  100. package/dist/oauth/index.js +40 -5
  101. package/dist/oauth/strategy/index.d.ts +0 -2
  102. package/dist/oauth/strategy/index.js +40 -17
  103. package/dist/oauth/types.d.ts +6 -6
  104. package/dist/oauth/utilities/isDuplicateKeyError.d.ts +7 -0
  105. package/dist/oauth/utilities/isDuplicateKeyError.js +14 -0
  106. package/dist/oauth/utilities/refreshTokens.js +3 -3
  107. package/dist/plugin/build-config.d.ts +21 -14
  108. package/dist/plugin/build-config.js +208 -17
  109. package/dist/storage-content-api/api-types.d.ts +168 -0
  110. package/dist/storage-content-api/api-types.js +6 -0
  111. package/dist/storage-content-api/client-uploads/ClientUploadHandler.d.ts +9 -0
  112. package/dist/storage-content-api/client-uploads/ClientUploadHandler.js +42 -0
  113. package/dist/storage-content-api/client-uploads/generateSignedURL.d.ts +13 -0
  114. package/dist/storage-content-api/client-uploads/generateSignedURL.js +39 -0
  115. package/dist/storage-content-api/client.d.ts +6 -0
  116. package/dist/storage-content-api/client.js +36 -0
  117. package/dist/storage-content-api/generateURL.d.ts +7 -0
  118. package/dist/storage-content-api/generateURL.js +8 -0
  119. package/dist/storage-content-api/handleDelete.d.ts +8 -0
  120. package/dist/storage-content-api/handleDelete.js +17 -0
  121. package/dist/storage-content-api/handleUpload.d.ts +11 -0
  122. package/dist/storage-content-api/handleUpload.js +144 -0
  123. package/dist/storage-content-api/index.d.ts +5 -0
  124. package/dist/storage-content-api/index.js +31 -0
  125. package/dist/storage-content-api/staticHandler.d.ts +10 -0
  126. package/dist/storage-content-api/staticHandler.js +56 -0
  127. package/dist/storage-content-api/types.d.ts +10 -0
  128. package/dist/storage-content-api/types.js +3 -0
  129. package/dist/storage-content-api/utilities/getSafeFilename.d.ts +12 -0
  130. package/dist/storage-content-api/utilities/getSafeFilename.js +61 -0
  131. package/dist/storage-content-api/utilities/index.d.ts +2 -0
  132. package/dist/storage-content-api/utilities/index.js +3 -0
  133. package/dist/templates/.env.example +5 -0
  134. package/dist/templates/README.md +19 -0
  135. package/dist/types/config.d.ts +2 -1
  136. package/dist/types/config.js +0 -2
  137. package/dist/types.d.ts +3 -1
  138. package/dist/utils/asset-collection.d.ts +3 -6
  139. package/dist/utils/asset-collection.js +10 -34
  140. package/dist/utils/build-lambda-zip.d.ts +14 -0
  141. package/dist/utils/build-lambda-zip.js +81 -0
  142. package/dist/utils/cache-bootstrap.d.ts +8 -0
  143. package/dist/utils/cache-bootstrap.js +18 -0
  144. package/dist/utils/config.js +1 -1
  145. package/dist/utils/env-management.d.ts +16 -7
  146. package/dist/utils/env-management.js +85 -64
  147. package/dist/utils/format-env-suffix.d.ts +12 -0
  148. package/dist/utils/format-env-suffix.js +13 -0
  149. package/dist/utils/formatter.js +3 -5
  150. package/dist/utils/lambda-config.d.ts +3 -1
  151. package/dist/utils/lambda-config.js +38 -32
  152. package/dist/utils/messages.d.ts +1 -1
  153. package/dist/utils/messages.js +22 -8
  154. package/dist/utils/package-manager.d.ts +24 -0
  155. package/dist/utils/package-manager.js +53 -0
  156. package/dist/utils/payload-config-ast.d.ts +22 -3
  157. package/dist/utils/payload-config-ast.js +96 -31
  158. package/dist/utils/payload-config-finder.d.ts +2 -2
  159. package/dist/utils/payload-config-finder.js +48 -9
  160. package/dist/utils/payload-config-modifier.d.ts +1 -1
  161. package/dist/utils/payload-config-modifier.js +61 -10
  162. package/dist/utils/payload-package-check.d.ts +12 -1
  163. package/dist/utils/payload-package-check.js +63 -5
  164. package/dist/utils/project.d.ts +3 -2
  165. package/dist/utils/project.js +29 -15
  166. package/dist/utils/resolve-environment.d.ts +14 -0
  167. package/dist/utils/resolve-environment.js +28 -0
  168. package/dist/utils/s3-upload.d.ts +0 -1
  169. package/dist/utils/s3-upload.js +10 -3
  170. package/dist/utils/token-display.js +11 -5
  171. package/dist/utils/typescript-validator.js +4 -6
  172. package/dist/utils/version-check.d.ts +3 -0
  173. package/dist/utils/version-check.js +38 -0
  174. package/package.json +29 -10
  175. package/dist/api/control-plane.d.ts.map +0 -1
  176. package/dist/api/control-plane.js.map +0 -1
  177. package/dist/api/figma-api.d.ts.map +0 -1
  178. package/dist/api/figma-api.js.map +0 -1
  179. package/dist/auth/browser.d.ts.map +0 -1
  180. package/dist/auth/browser.js.map +0 -1
  181. package/dist/auth/callback-server.d.ts.map +0 -1
  182. package/dist/auth/callback-server.js.map +0 -1
  183. package/dist/auth/crypto-utils.d.ts.map +0 -1
  184. package/dist/auth/crypto-utils.js.map +0 -1
  185. package/dist/auth/jwt-validator.d.ts.map +0 -1
  186. package/dist/auth/jwt-validator.js.map +0 -1
  187. package/dist/auth/oauth-flow.d.ts.map +0 -1
  188. package/dist/auth/oauth-flow.js.map +0 -1
  189. package/dist/auth/pkce.d.ts.map +0 -1
  190. package/dist/auth/pkce.js.map +0 -1
  191. package/dist/auth/project-token.d.ts.map +0 -1
  192. package/dist/auth/project-token.js.map +0 -1
  193. package/dist/auth/refresh.d.ts.map +0 -1
  194. package/dist/auth/refresh.js.map +0 -1
  195. package/dist/auth/token-store.d.ts.map +0 -1
  196. package/dist/auth/token-store.js.map +0 -1
  197. package/dist/auth/types.d.ts.map +0 -1
  198. package/dist/auth/types.js.map +0 -1
  199. package/dist/cli.d.ts.map +0 -1
  200. package/dist/cli.js.map +0 -1
  201. package/dist/commands/deploy.d.ts.map +0 -1
  202. package/dist/commands/deploy.js.map +0 -1
  203. package/dist/commands/init.d.ts.map +0 -1
  204. package/dist/commands/init.js.map +0 -1
  205. package/dist/commands/list-tokens.d.ts.map +0 -1
  206. package/dist/commands/list-tokens.js.map +0 -1
  207. package/dist/commands/login.d.ts.map +0 -1
  208. package/dist/commands/login.js.map +0 -1
  209. package/dist/commands/logout.d.ts.map +0 -1
  210. package/dist/commands/logout.js.map +0 -1
  211. package/dist/config/oauth.d.ts.map +0 -1
  212. package/dist/config/oauth.js.map +0 -1
  213. package/dist/constants.d.ts.map +0 -1
  214. package/dist/constants.js.map +0 -1
  215. package/dist/exports/client.d.ts.map +0 -1
  216. package/dist/exports/client.js.map +0 -1
  217. package/dist/index.d.ts.map +0 -1
  218. package/dist/index.js.map +0 -1
  219. package/dist/oauth/components/LoginButton/index.d.ts.map +0 -1
  220. package/dist/oauth/components/LoginButton/index.js.map +0 -1
  221. package/dist/oauth/components/LogoutButton/index.d.ts.map +0 -1
  222. package/dist/oauth/components/LogoutButton/index.js.map +0 -1
  223. package/dist/oauth/defaults.d.ts.map +0 -1
  224. package/dist/oauth/defaults.js.map +0 -1
  225. package/dist/oauth/endpoints/getLoginEndpoint.d.ts.map +0 -1
  226. package/dist/oauth/endpoints/getLoginEndpoint.js.map +0 -1
  227. package/dist/oauth/endpoints/getLogoutEndpoint.d.ts.map +0 -1
  228. package/dist/oauth/endpoints/getLogoutEndpoint.js.map +0 -1
  229. package/dist/oauth/endpoints/getMetaEndpoint.d.ts.map +0 -1
  230. package/dist/oauth/endpoints/getMetaEndpoint.js.map +0 -1
  231. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.d.ts.map +0 -1
  232. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js.map +0 -1
  233. package/dist/oauth/exports/client.d.ts.map +0 -1
  234. package/dist/oauth/exports/client.js.map +0 -1
  235. package/dist/oauth/hooks/afterLogout.d.ts.map +0 -1
  236. package/dist/oauth/hooks/afterLogout.js.map +0 -1
  237. package/dist/oauth/hooks/me.d.ts.map +0 -1
  238. package/dist/oauth/hooks/me.js.map +0 -1
  239. package/dist/oauth/hooks/refresh.d.ts.map +0 -1
  240. package/dist/oauth/hooks/refresh.js.map +0 -1
  241. package/dist/oauth/index.d.ts.map +0 -1
  242. package/dist/oauth/index.js.map +0 -1
  243. package/dist/oauth/strategy/index.d.ts.map +0 -1
  244. package/dist/oauth/strategy/index.js.map +0 -1
  245. package/dist/oauth/types.d.ts.map +0 -1
  246. package/dist/oauth/types.js.map +0 -1
  247. package/dist/oauth/utilities/clearCookie.d.ts.map +0 -1
  248. package/dist/oauth/utilities/clearCookie.js.map +0 -1
  249. package/dist/oauth/utilities/createCookieOptions.d.ts.map +0 -1
  250. package/dist/oauth/utilities/createCookieOptions.js.map +0 -1
  251. package/dist/oauth/utilities/createDebugLogger.d.ts.map +0 -1
  252. package/dist/oauth/utilities/createDebugLogger.js.map +0 -1
  253. package/dist/oauth/utilities/extractOrigin.d.ts.map +0 -1
  254. package/dist/oauth/utilities/extractOrigin.js.map +0 -1
  255. package/dist/oauth/utilities/getAdminCollectionSlug.d.ts.map +0 -1
  256. package/dist/oauth/utilities/getAdminCollectionSlug.js.map +0 -1
  257. package/dist/oauth/utilities/getAdminPath.d.ts +0 -8
  258. package/dist/oauth/utilities/getAdminPath.d.ts.map +0 -1
  259. package/dist/oauth/utilities/getAdminPath.js +0 -9
  260. package/dist/oauth/utilities/getAdminPath.js.map +0 -1
  261. package/dist/oauth/utilities/getAuthorizeURL.d.ts.map +0 -1
  262. package/dist/oauth/utilities/getAuthorizeURL.js.map +0 -1
  263. package/dist/oauth/utilities/getCookieExpiration.d.ts.map +0 -1
  264. package/dist/oauth/utilities/getCookieExpiration.js.map +0 -1
  265. package/dist/oauth/utilities/getSecondsFromTokenExp.d.ts.map +0 -1
  266. package/dist/oauth/utilities/getSecondsFromTokenExp.js.map +0 -1
  267. package/dist/oauth/utilities/getTokenExp.d.ts.map +0 -1
  268. package/dist/oauth/utilities/getTokenExp.js.map +0 -1
  269. package/dist/oauth/utilities/getUsernameField.d.ts.map +0 -1
  270. package/dist/oauth/utilities/getUsernameField.js.map +0 -1
  271. package/dist/oauth/utilities/hasUserTokenPropsChanged.d.ts.map +0 -1
  272. package/dist/oauth/utilities/hasUserTokenPropsChanged.js.map +0 -1
  273. package/dist/oauth/utilities/mergeHeaders.d.ts.map +0 -1
  274. package/dist/oauth/utilities/mergeHeaders.js.map +0 -1
  275. package/dist/oauth/utilities/refreshTokens.d.ts.map +0 -1
  276. package/dist/oauth/utilities/refreshTokens.js.map +0 -1
  277. package/dist/plugin/adapter.d.ts.map +0 -1
  278. package/dist/plugin/adapter.js.map +0 -1
  279. package/dist/plugin/build-config.d.ts.map +0 -1
  280. package/dist/plugin/build-config.js.map +0 -1
  281. package/dist/types/config.d.ts.map +0 -1
  282. package/dist/types/config.js.map +0 -1
  283. package/dist/types.d.ts.map +0 -1
  284. package/dist/types.js.map +0 -1
  285. package/dist/utils/asset-collection.d.ts.map +0 -1
  286. package/dist/utils/asset-collection.js.map +0 -1
  287. package/dist/utils/build-detection.d.ts.map +0 -1
  288. package/dist/utils/build-detection.js.map +0 -1
  289. package/dist/utils/config.d.ts.map +0 -1
  290. package/dist/utils/config.js.map +0 -1
  291. package/dist/utils/download-template.d.ts.map +0 -1
  292. package/dist/utils/download-template.js.map +0 -1
  293. package/dist/utils/env-management.d.ts.map +0 -1
  294. package/dist/utils/env-management.js.map +0 -1
  295. package/dist/utils/format.d.ts.map +0 -1
  296. package/dist/utils/format.js.map +0 -1
  297. package/dist/utils/formatter.d.ts.map +0 -1
  298. package/dist/utils/formatter.js.map +0 -1
  299. package/dist/utils/git.d.ts.map +0 -1
  300. package/dist/utils/git.js.map +0 -1
  301. package/dist/utils/is-debug.d.ts.map +0 -1
  302. package/dist/utils/is-debug.js.map +0 -1
  303. package/dist/utils/lambda-config.d.ts.map +0 -1
  304. package/dist/utils/lambda-config.js.map +0 -1
  305. package/dist/utils/log.d.ts.map +0 -1
  306. package/dist/utils/log.js.map +0 -1
  307. package/dist/utils/messages.d.ts.map +0 -1
  308. package/dist/utils/messages.js.map +0 -1
  309. package/dist/utils/package-manager.d.ts.map +0 -1
  310. package/dist/utils/package-manager.js.map +0 -1
  311. package/dist/utils/payload-config-ast.d.ts.map +0 -1
  312. package/dist/utils/payload-config-ast.js.map +0 -1
  313. package/dist/utils/payload-config-finder.d.ts.map +0 -1
  314. package/dist/utils/payload-config-finder.js.map +0 -1
  315. package/dist/utils/payload-config-modifier.d.ts.map +0 -1
  316. package/dist/utils/payload-config-modifier.js.map +0 -1
  317. package/dist/utils/payload-package-check.d.ts.map +0 -1
  318. package/dist/utils/payload-package-check.js.map +0 -1
  319. package/dist/utils/project.d.ts.map +0 -1
  320. package/dist/utils/project.js.map +0 -1
  321. package/dist/utils/s3-upload.d.ts.map +0 -1
  322. package/dist/utils/s3-upload.js.map +0 -1
  323. package/dist/utils/token-display.d.ts.map +0 -1
  324. package/dist/utils/token-display.js.map +0 -1
  325. package/dist/utils/typescript-validator.d.ts.map +0 -1
  326. package/dist/utils/typescript-validator.js.map +0 -1
@@ -1,16 +1,15 @@
1
1
  import { APIError, generateCookie, parseCookies } from 'payload';
2
- import { getSafeRedirect } from 'payload/shared';
3
- import { getProjectToken } from '../../api/figma-api.js';
2
+ import { formatAdminURL, getSafeRedirect } from 'payload/shared';
3
+ import { getProjectToken, getUserInfo } from '../../api/figma-api.js';
4
4
  import { createCookieOptions } from '../utilities/createCookieOptions.js';
5
5
  import { createDebugLogger } from '../utilities/createDebugLogger.js';
6
6
  import { extractOrigin } from '../utilities/extractOrigin.js';
7
- import { getAdminPath } from '../utilities/getAdminPath.js';
8
7
  import { getCookieExpiration } from '../utilities/getCookieExpiration.js';
9
8
  const isAbsoluteURL = (url)=>/^[a-z][a-z\d+.-]*:/.test(url);
10
9
  export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug, pluginOptions, strategy })=>({
11
10
  handler: async (req)=>{
12
11
  const { config } = req.payload;
13
- const adminPath = getAdminPath(config);
12
+ const adminRoute = config.routes?.admin || '/admin';
14
13
  try {
15
14
  await strategy.ensureMeta();
16
15
  const path = req.pathname;
@@ -37,9 +36,16 @@ export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug,
37
36
  }
38
37
  const stateRaw = jsonBody.state;
39
38
  const state = JSON.parse(Buffer.from(stateRaw, 'base64').toString('utf-8'));
40
- const redirectDestination = state.serverURL || pluginOptions.redirectServerURL || config.serverURL;
41
- let failedRedirect = `${redirectDestination}${adminPath}/login`;
42
- let redirectToUse = `${redirectDestination}${adminPath}`;
39
+ const redirectServerURL = state.serverURL || pluginOptions.redirectServerURL || config.serverURL;
40
+ let failedRedirect = formatAdminURL({
41
+ adminRoute,
42
+ path: '/login',
43
+ serverURL: redirectServerURL
44
+ });
45
+ let redirectToUse = formatAdminURL({
46
+ adminRoute,
47
+ serverURL: redirectServerURL
48
+ });
43
49
  if (state.redirect) {
44
50
  redirectToUse = state.redirect;
45
51
  }
@@ -126,16 +132,20 @@ export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug,
126
132
  code,
127
133
  code_verifier: req.payload.decrypt(state.verifier),
128
134
  grant_type: 'authorization_code',
129
- redirect_uri: `${redirectDestination}${config?.routes?.api || '/api'}/${collection.slug}/${endpointSlug}/login`
135
+ redirect_uri: formatAdminURL({
136
+ apiRoute: config.routes?.api || '/api',
137
+ path: `/${collection.slug}/${endpointSlug}/login`,
138
+ serverURL: redirectServerURL
139
+ })
130
140
  };
141
+ if (strategy.collectionOptions.clientSecret) {
142
+ body.client_secret = strategy.collectionOptions.clientSecret;
143
+ }
131
144
  debugLogger.info({
132
145
  msg: 'Exchanging code for access token',
133
146
  path,
134
147
  requestBody: body
135
148
  });
136
- if (strategy.clientSecret) {
137
- body.client_secret = strategy.clientSecret;
138
- }
139
149
  const tokenRes = await fetch(strategy.meta?.token_endpoint, {
140
150
  body: new URLSearchParams(body),
141
151
  headers: {
@@ -149,12 +159,40 @@ export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug,
149
159
  tokenRes
150
160
  });
151
161
  const { access_token, error, error_description, expires_in: refreshTokenExpires } = tokenRes;
152
- debugLogger.info({
153
- msg: 'tokenResss',
154
- tokenRes
155
- });
162
+ if (error) {
163
+ req.payload.logger.error('Error swapping access code with access token:');
164
+ req.payload.logger.error({
165
+ err: error,
166
+ error_description
167
+ });
168
+ return Response.redirect(failedRedirect);
169
+ }
170
+ // Fetch Figma user info for handle and profile image
171
+ let figmaUserInfo = null;
172
+ try {
173
+ figmaUserInfo = await getUserInfo(access_token);
174
+ debugLogger.info({
175
+ figmaUserInfo,
176
+ msg: 'Fetched Figma user info'
177
+ });
178
+ } catch (err) {
179
+ // Non-fatal: user will just not have handle/image
180
+ debugLogger.error({
181
+ err,
182
+ msg: 'Failed to fetch Figma user info'
183
+ });
184
+ }
185
+ if (!access_token) {
186
+ const errMsg = 'No access_token was returned from the identity provider.';
187
+ req.payload.logger.error({
188
+ msg: errMsg,
189
+ path,
190
+ tokenRes
191
+ });
192
+ throw new APIError(errMsg);
193
+ }
156
194
  // Swap for project token
157
- const project_token = await getProjectToken(tokenRes.access_token, 'someproject');
195
+ const project_token = await getProjectToken(access_token, config.custom.figma.contentSystemId);
158
196
  const refresh_token = access_token;
159
197
  // Store project token as access_token
160
198
  const token = project_token.token;
@@ -172,14 +210,6 @@ export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug,
172
210
  headers: req.headers,
173
211
  pluginOptions
174
212
  });
175
- if (error) {
176
- req.payload.logger.error('Error swapping access code with access token:');
177
- req.payload.logger.error({
178
- err: error,
179
- error_description
180
- });
181
- return Response.redirect(failedRedirect);
182
- }
183
213
  // get the payloadRedirect cookie value
184
214
  const cookies = parseCookies(req.headers);
185
215
  const payloadRedirect = 'payloadRedirect' in cookies ? cookies.payloadRedirect : '';
@@ -216,6 +246,21 @@ export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug,
216
246
  value: token
217
247
  });
218
248
  req.responseHeaders.append('Set-Cookie', tokenCookie);
249
+ // Store user info in short-lived cookie for defaultVerify to consume
250
+ if (figmaUserInfo) {
251
+ const userInfoValue = Buffer.from(JSON.stringify({
252
+ handle: figmaUserInfo.handle,
253
+ img_url: figmaUserInfo.img_url
254
+ })).toString('base64');
255
+ const userInfoCookie = generateCookie({
256
+ ...cookieOptions,
257
+ name: 'figma-user-info',
258
+ expires: new Date(Date.now() + 60_000),
259
+ returnCookieAsObject: false,
260
+ value: userInfoValue
261
+ });
262
+ req.responseHeaders.append('Set-Cookie', userInfoCookie);
263
+ }
219
264
  return Response.redirect(redirectToUse);
220
265
  } catch (err) {
221
266
  req.payload.logger.error({
@@ -1,9 +1,9 @@
1
1
  import jwt from 'jsonwebtoken';
2
2
  import { parseCookies } from 'payload';
3
+ import { formatAdminURL } from 'payload/shared';
3
4
  import { clearCookie } from '../utilities/clearCookie.js';
4
5
  import { createCookieOptions } from '../utilities/createCookieOptions.js';
5
6
  import { createDebugLogger } from '../utilities/createDebugLogger.js';
6
- import { getAdminPath } from '../utilities/getAdminPath.js';
7
7
  export const getLogoutEndpoint = ({ collection, endpointSlug, pluginOptions, strategy })=>({
8
8
  handler: async (req)=>{
9
9
  const debugLogger = createDebugLogger(req.payload, pluginOptions.debug);
@@ -23,12 +23,15 @@ export const getLogoutEndpoint = ({ collection, endpointSlug, pluginOptions, str
23
23
  }
24
24
  try {
25
25
  await strategy.ensureMeta();
26
- const baseRedirectDestination = pluginOptions.redirectServerURL || config.serverURL;
27
- let successfulLogoutRedirectDest = `${baseRedirectDestination}${getAdminPath(config)}`;
26
+ const redirectServerlURL = pluginOptions.redirectServerURL || config.serverURL;
27
+ let successfulLogoutRedirectDest = formatAdminURL({
28
+ adminRoute: config.routes?.admin || '/admin',
29
+ serverURL: redirectServerlURL
30
+ });
28
31
  if (typeof req.query.redirect === 'string') {
29
32
  successfulLogoutRedirectDest = req.query.redirect;
30
33
  }
31
- if (!baseRedirectDestination && !req.query.redirect) {
34
+ if (!redirectServerlURL && !req.query.redirect) {
32
35
  debugLogger.error({
33
36
  msg: 'No redirect URL provided',
34
37
  path: req.pathname
@@ -1,3 +1,4 @@
1
+ import { fieldAffectsData } from 'payload/shared';
1
2
  import { defaultVerify } from './defaults.js';
2
3
  import { getLoginEndpoint } from './endpoints/getLoginEndpoint.js';
3
4
  import { getLogoutEndpoint } from './endpoints/getLogoutEndpoint.js';
@@ -84,14 +85,45 @@ export const oAuth2Plugin = (pluginOptions)=>(config)=>{
84
85
  if (collectionOptions.usePayloadJWT) {
85
86
  cookieName = `${config.cookiePrefix || 'payload'}-token`;
86
87
  }
88
+ // Check if email field exists, if not add it
89
+ const hasEmailField = existingCollection.fields.some((field)=>'name' in field && field.name === 'email');
90
+ // Add email field to collection before getting username field
91
+ // This ensures getUsernameField can find the email field if it's configured as the username
92
+ const collectionWithEmail = hasEmailField ? existingCollection : {
93
+ ...existingCollection,
94
+ fields: [
95
+ ...existingCollection.fields,
96
+ {
97
+ name: 'email',
98
+ type: 'email',
99
+ admin: {
100
+ description: 'Managed by Figma',
101
+ readOnly: true
102
+ },
103
+ unique: true
104
+ }
105
+ ]
106
+ };
87
107
  const usernameField = getUsernameField({
88
- collection: existingCollection,
108
+ collection: collectionWithEmail,
89
109
  collectionOptions
90
110
  });
111
+ // Make username field readOnly (and add description for email fields)
112
+ const readOnlyUsernameField = {
113
+ ...usernameField,
114
+ admin: {
115
+ ...usernameField.admin || {},
116
+ ...usernameField.name === 'email' ? {
117
+ description: 'Managed by Figma'
118
+ } : {},
119
+ readOnly: true
120
+ }
121
+ };
122
+ const isUsernameFieldString = typeof adminCollectionOptions.usernameField === 'string';
91
123
  const fields = [
92
- ...existingCollection.fields,
93
- ...typeof adminCollectionOptions.usernameField === 'string' ? [] : [
94
- usernameField
124
+ ...collectionWithEmail.fields.map((field)=>fieldAffectsData(field) && field.name === usernameField.name ? readOnlyUsernameField : field),
125
+ ...isUsernameFieldString ? [] : [
126
+ readOnlyUsernameField
95
127
  ]
96
128
  ];
97
129
  if (disabled) {
@@ -102,7 +134,6 @@ export const oAuth2Plugin = (pluginOptions)=>(config)=>{
102
134
  }
103
135
  const strategy = new Strategy({
104
136
  clientID: collectionOptions.clientID,
105
- clientSecret: collectionOptions.clientSecret,
106
137
  collection: existingCollection,
107
138
  collectionOptions,
108
139
  cookieName,
@@ -134,6 +165,10 @@ export const oAuth2Plugin = (pluginOptions)=>(config)=>{
134
165
  }
135
166
  return {
136
167
  ...existingCollection,
168
+ access: {
169
+ ...existingCollection.access || {},
170
+ create: ()=>false
171
+ },
137
172
  auth: {
138
173
  ...typeof existingCollection.auth === 'object' ? existingCollection.auth : {},
139
174
  disableLocalStrategy,
@@ -4,7 +4,6 @@ import * as jose from 'jose';
4
4
  import type { CollectionOptions, PluginOptions, VerifyFunction } from '../types.js';
5
5
  export interface Options {
6
6
  clientID: string;
7
- clientSecret?: string;
8
7
  collection: CollectionConfig;
9
8
  collectionOptions: CollectionOptions;
10
9
  cookieName: string;
@@ -16,7 +15,6 @@ export interface Options {
16
15
  }
17
16
  export declare class Strategy {
18
17
  clientID: string;
19
- clientSecret?: string;
20
18
  collection: CollectionConfig;
21
19
  collectionOptions: CollectionOptions;
22
20
  cookieName: string;
@@ -1,14 +1,13 @@
1
1
  import * as jose from 'jose';
2
2
  import { APIError, parseCookies } from 'payload';
3
- import { validateProjectToken } from '../../auth/jwt-validator.js';
4
- import { getEnvironment } from '../../constants.js';
3
+ import { JWTValidationError, validateProjectToken } from '../../auth/jwt-validator.js';
4
+ import { getInfraEnvironment } from '../../constants.js';
5
5
  import { createDebugLogger } from '../utilities/createDebugLogger.js';
6
6
  import { getTokenExp } from '../utilities/getTokenExp.js';
7
7
  import { mergeHeaders } from '../utilities/mergeHeaders.js';
8
8
  import { refreshTokens } from '../utilities/refreshTokens.js';
9
9
  export class Strategy {
10
10
  clientID;
11
- clientSecret;
12
11
  collection;
13
12
  collectionOptions;
14
13
  cookieName;
@@ -28,7 +27,6 @@ export class Strategy {
28
27
  this.verify = options.verify;
29
28
  this.cookieName = options.cookieName;
30
29
  this.clientID = options.clientID;
31
- this.clientSecret = options.clientSecret;
32
30
  this.identityMetadataURL = options.identityMetadata;
33
31
  this.name = options.strategyName;
34
32
  this.collection = options.collection;
@@ -63,7 +61,11 @@ export class Strategy {
63
61
  }
64
62
  }
65
63
  if (!oauthToken) {
66
- if (refreshToken && canSetHeaders) {
64
+ // Attempt refresh even when canSetHeaders=false (e.g., during RSC navigation).
65
+ // This allows authentication to succeed for the current request even when
66
+ // cookies cannot be updated. The cookie will be refreshed on the next
67
+ // full page load when canSetHeaders=true.
68
+ if (refreshToken) {
67
69
  debugLogger.info({
68
70
  msg: 'No access token found, but refresh token exists. Attempting to refresh...',
69
71
  refreshToken
@@ -83,11 +85,20 @@ export class Strategy {
83
85
  msg: 'Token refreshed. Verifying...',
84
86
  verifyResult
85
87
  });
86
- if (verifyResult.responseHeaders) {
87
- mergeHeaders(verifyResult.responseHeaders, refreshed.headers);
88
+ // Only return response headers (to set cookies) when canSetHeaders is true.
89
+ // During RSC navigation, canSetHeaders=false because response streaming
90
+ // has already started and cookies cannot be modified.
91
+ if (canSetHeaders) {
92
+ if (verifyResult.responseHeaders) {
93
+ mergeHeaders(verifyResult.responseHeaders, refreshed.headers);
94
+ }
95
+ return {
96
+ responseHeaders: refreshed.headers,
97
+ user: verifyResult.user
98
+ };
88
99
  }
100
+ // Authenticate this request without updating cookies
89
101
  return {
90
- responseHeaders: refreshed.headers,
91
102
  user: verifyResult.user
92
103
  };
93
104
  } else {
@@ -97,11 +108,10 @@ export class Strategy {
97
108
  refreshToken
98
109
  });
99
110
  }
100
- } else {
101
- return {
102
- user: null
103
- };
104
111
  }
112
+ return {
113
+ user: null
114
+ };
105
115
  }
106
116
  let oauthTokenVerifyResult = null;
107
117
  // First, try to verify token
@@ -136,7 +146,10 @@ export class Strategy {
136
146
  });
137
147
  }
138
148
  }
139
- if (oauthTokenVerifyResult instanceof Error && oauthTokenVerifyResult.name === 'TokenExpiredError' && refreshToken && !this.collectionOptions.usePayloadJWT && canSetHeaders) {
149
+ // Handle expired access token with valid refresh token.
150
+ // Same pattern as above: refresh regardless of canSetHeaders to support RSC navigation,
151
+ // but only update cookies when canSetHeaders=true.
152
+ if (oauthTokenVerifyResult instanceof JWTValidationError && oauthTokenVerifyResult.code === 'EXPIRED' && refreshToken && !this.collectionOptions.usePayloadJWT) {
140
153
  const refreshed = await refreshTokens({
141
154
  payload,
142
155
  refreshToken,
@@ -157,11 +170,17 @@ export class Strategy {
157
170
  msg: 'Token refreshed. Verifying...',
158
171
  verifyResult
159
172
  });
160
- if (verifyResult.responseHeaders) {
161
- mergeHeaders(verifyResult.responseHeaders, refreshed.headers);
173
+ if (canSetHeaders) {
174
+ if (verifyResult.responseHeaders) {
175
+ mergeHeaders(verifyResult.responseHeaders, refreshed.headers);
176
+ }
177
+ return {
178
+ responseHeaders: refreshed.headers,
179
+ user: verifyResult.user
180
+ };
162
181
  }
182
+ // Authenticate this request without updating cookies
163
183
  return {
164
- responseHeaders: refreshed.headers,
165
184
  user: verifyResult.user
166
185
  };
167
186
  } else {
@@ -200,6 +219,10 @@ export class Strategy {
200
219
  for(let attempt = 1; attempt <= 5; attempt++){
201
220
  try {
202
221
  this.meta = await fetch(this.identityMetadataURL).then((res)=>res.json());
222
+ if (this.meta) {
223
+ // TODO: This is a hack to get the DefaultLoginButton to work with dynamic OAuth client registration
224
+ this.meta.authorization_endpoint = this.meta?.authorization_endpoint + '/cms';
225
+ }
203
226
  this.debugLog(`fetchMeta - success on attempt ${attempt}`);
204
227
  if (this.meta?.jwks_uri) {
205
228
  this.jwks = await fetch(this.meta.jwks_uri).then((res)=>res.json());
@@ -259,7 +282,7 @@ export class Strategy {
259
282
  }
260
283
  async jwtVerify({ payload, token }) {
261
284
  try {
262
- const verified = await validateProjectToken(token, getEnvironment());
285
+ const verified = await validateProjectToken(token, getInfraEnvironment());
263
286
  if (typeof verified !== 'string') {
264
287
  return verified;
265
288
  }
@@ -30,7 +30,7 @@ export interface CollectionOptions {
30
30
  * Set to false to only accept the JWT from cookies
31
31
  */
32
32
  disableJWTFromHeader?: boolean;
33
- disableLocalStrategy?: boolean | IncomingAuthType['disableLocalStrategy'];
33
+ disableLocalStrategy?: false | IncomingAuthType['disableLocalStrategy'];
34
34
  /**
35
35
  * The logout button will either redirect to the IDP logout screen or
36
36
  * automatically log the user out of the IDP depending on provider.
@@ -112,11 +112,6 @@ export interface PluginOptions {
112
112
  * @default 'payload-oauth-token'
113
113
  */
114
114
  cookieName?: string;
115
- /**
116
- * Debug mode will log additional information to the console.
117
- *
118
- * NOTE: This will log sensitive information to the console.
119
- */
120
115
  /**
121
116
  * Accepts incoming request and allows for modification of cookie options
122
117
  */
@@ -125,6 +120,11 @@ export interface PluginOptions {
125
120
  cookieOptions: CookieOptions;
126
121
  headers: Headers;
127
122
  }) => CookieOptions;
123
+ /**
124
+ * Debug mode will log additional information to the console.
125
+ *
126
+ * NOTE: This will log sensitive information to the console.
127
+ */
128
128
  debug?: boolean;
129
129
  /**
130
130
  * Disables the plugin functionality while leaving in types, fields and component modifications.
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Check if an error is a duplicate key/unique constraint violation from Content API.
3
+ *
4
+ * Content API returns HTTP 409 with "conflict" or "already exists" in the message.
5
+ */
6
+ export declare function isDuplicateKeyError(error: unknown): boolean;
7
+ //# sourceMappingURL=isDuplicateKeyError.d.ts.map
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Check if an error is a duplicate key/unique constraint violation from Content API.
3
+ *
4
+ * Content API returns HTTP 409 with "conflict" or "already exists" in the message.
5
+ */ export function isDuplicateKeyError(error) {
6
+ if (!error || typeof error !== 'object') {
7
+ return false;
8
+ }
9
+ const err = error;
10
+ const message = typeof err.message === 'string' ? err.message : '';
11
+ return message.includes('409') || message.toLowerCase().includes('conflict') || message.toLowerCase().includes('already exists');
12
+ }
13
+
14
+ //# sourceMappingURL=isDuplicateKeyError.js.map
@@ -1,7 +1,7 @@
1
1
  import { generateCookie } from 'payload';
2
2
  import { getProjectToken } from '../../api/figma-api.js';
3
3
  import { validateProjectToken } from '../../auth/jwt-validator.js';
4
- import { getEnvironment } from '../../constants.js';
4
+ import { getInfraEnvironment } from '../../constants.js';
5
5
  import { createCookieOptions } from './createCookieOptions.js';
6
6
  import { createDebugLogger } from './createDebugLogger.js';
7
7
  import { getCookieExpiration } from './getCookieExpiration.js';
@@ -16,7 +16,7 @@ export const refreshTokens = async ({ payload, refreshToken, strategy })=>{
16
16
  // so we will refresh both tokens
17
17
  try {
18
18
  // Get another project token
19
- const { expiresAt, token } = await getProjectToken(refreshToken, 'someproject');
19
+ const { expiresAt, token } = await getProjectToken(refreshToken, payload.config.custom.figma.contentSystemId);
20
20
  debugLogger.info({
21
21
  expiresAt,
22
22
  msg: 'Received new tokens from Figma API',
@@ -48,7 +48,7 @@ export const refreshTokens = async ({ payload, refreshToken, strategy })=>{
48
48
  value: token
49
49
  });
50
50
  headers.append('Set-Cookie', tokenCookie);
51
- const decodedOauthToken = await validateProjectToken(token, getEnvironment());
51
+ const decodedOauthToken = await validateProjectToken(token, getInfraEnvironment());
52
52
  return {
53
53
  decodedOauthToken,
54
54
  headers,
@@ -10,34 +10,41 @@ import type { Config, SanitizedConfig } from 'payload';
10
10
  * @example
11
11
  * // Minimal config
12
12
  * const config: FigmaConfig = {
13
+ * figma: {
14
+ * contentSystemId: process.env.FIGMA_CONTENT_API_CONTENT_SYSTEM_ID!
15
+ * },
13
16
  * collections: [...]
14
17
  * }
15
18
  *
16
19
  * @example
17
20
  * // With custom editor
18
21
  * const config: FigmaConfig = {
22
+ * figma: {
23
+ * contentSystemId: process.env.FIGMA_CONTENT_API_CONTENT_SYSTEM_ID!
24
+ * },
19
25
  * collections: [...],
20
26
  * editor: lexicalEditor({ features: [...] })
21
27
  * }
28
+ *
29
+ * @example
30
+ * // Disable Content System (use custom db)
31
+ * const config: FigmaConfig = {
32
+ * figma: {
33
+ * contentSystemId: process.env.FIGMA_CONTENT_API_CONTENT_SYSTEM_ID!,
34
+ * useContentSystem: false
35
+ * },
36
+ * db: mongooseAdapter({ url: process.env.DATABASE_URI }),
37
+ * collections: [...]
38
+ * }
22
39
  */
23
40
  export type FigmaConfig = {
24
41
  editor?: Config['editor'];
25
42
  } & {
26
43
  figma: {
27
- region: string;
28
- tenantId: string;
44
+ contentSystemId: string;
45
+ storage?: boolean;
29
46
  useContentSystem?: boolean;
30
47
  };
31
- } & Omit<Config, 'editor' | 'secret' | 'db'> & Partial<Pick<Config, 'db'>>;
32
- /**
33
- * Figma platform wrapper for Payload's buildConfig.
34
- * Automatically injects:
35
- * - Figma database adapter
36
- * - Secret (platform-provided)
37
- * - Default lexicalEditor (if no custom editor specified)
38
- *
39
- * @param config - Payload configuration (db and secret omitted, editor optional)
40
- * @returns Promise<SanitizedConfig> - Built Payload configuration
41
- */
42
- export declare function buildConfig(config: FigmaConfig): Promise<SanitizedConfig>;
48
+ } & Omit<Config, 'db' | 'editor' | 'secret'> & Partial<Pick<Config, 'db'>>;
49
+ export declare function buildFigmaConfig(config: FigmaConfig): Promise<SanitizedConfig>;
43
50
  //# sourceMappingURL=build-config.d.ts.map