@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 +0,0 @@
1
- {"version":3,"sources":["../../src/auth/callback-server.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { CallbackError, CallbackServer } from './callback-server.js'\n\ndescribe('CallbackServer', () => {\n describe('waitForCallback', () => {\n it('should resolve with code and state on successful callback', async () => {\n const server = new CallbackServer({ port: 3001, timeoutMs: 5000 })\n const expectedState = 'test-state-123'\n\n // Start waiting for callback\n const callbackPromise = server.waitForCallback(expectedState)\n\n // Simulate OAuth callback\n await fetch(`http://localhost:3001/callback?code=auth-code-123&state=${expectedState}`)\n\n const result = await callbackPromise\n expect(result.code).toBe('auth-code-123')\n expect(result.state).toBe(expectedState)\n\n server.stop()\n })\n\n it('should reject with CallbackError on state mismatch', async () => {\n const server = new CallbackServer({ port: 3002, timeoutMs: 5000 })\n const expectedState = 'test-state-123'\n\n const callbackPromise = server.waitForCallback(expectedState)\n\n // Send wrong state\n const fetchPromise = fetch(\n `http://localhost:3002/callback?code=auth-code-123&state=wrong-state`,\n )\n\n await expect(callbackPromise).rejects.toThrow(CallbackError)\n await expect(callbackPromise).rejects.toThrow('State mismatch')\n\n // Wait for fetch to complete\n await fetchPromise\n\n server.stop()\n })\n\n it('should reject with CallbackError on OAuth error', async () => {\n const server = new CallbackServer({ port: 3003, timeoutMs: 5000 })\n const expectedState = 'test-state-123'\n\n const callbackPromise = server.waitForCallback(expectedState)\n\n // Send OAuth error\n const fetchPromise = fetch(\n `http://localhost:3003/callback?error=access_denied&error_description=User+denied`,\n )\n\n await expect(callbackPromise).rejects.toThrow(CallbackError)\n await expect(callbackPromise).rejects.toThrow('access_denied')\n\n // Wait for fetch to complete\n await fetchPromise\n\n server.stop()\n })\n\n it('should reject with CallbackError on timeout', async () => {\n const server = new CallbackServer({ port: 3005, timeoutMs: 100 })\n const expectedState = 'test-state-123'\n\n const callbackPromise = server.waitForCallback(expectedState)\n\n // Don't send callback - let it timeout\n await expect(callbackPromise).rejects.toThrow(CallbackError)\n await expect(callbackPromise).rejects.toThrow('timed out')\n\n server.stop()\n }, 1000)\n\n it('should return 404 for non-callback paths', async () => {\n const server = new CallbackServer({ port: 3006, timeoutMs: 200 })\n const expectedState = 'test-state-123'\n\n // Start server\n const callbackPromise = server.waitForCallback(expectedState).catch(() => {\n // Ignore timeout error\n })\n\n // Wait a bit for server to start\n await new Promise((resolve) => setTimeout(resolve, 50))\n\n // Try to access wrong path\n const response = await fetch('http://localhost:3006/not-callback')\n expect(response.status).toBe(404)\n\n // Clean up\n server.stop()\n\n // Wait for promise to complete\n await callbackPromise\n }, 2000)\n })\n})\n"],"names":["describe","expect","it","CallbackError","CallbackServer","server","port","timeoutMs","expectedState","callbackPromise","waitForCallback","fetch","result","code","toBe","state","stop","fetchPromise","rejects","toThrow","catch","Promise","resolve","setTimeout","response","status"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,aAAa,EAAEC,cAAc,QAAQ,uBAAsB;AAEpEJ,SAAS,kBAAkB;IACzBA,SAAS,mBAAmB;QAC1BE,GAAG,6DAA6D;YAC9D,MAAMG,SAAS,IAAID,eAAe;gBAAEE,MAAM;gBAAMC,WAAW;YAAK;YAChE,MAAMC,gBAAgB;YAEtB,6BAA6B;YAC7B,MAAMC,kBAAkBJ,OAAOK,eAAe,CAACF;YAE/C,0BAA0B;YAC1B,MAAMG,MAAM,CAAC,wDAAwD,EAAEH,eAAe;YAEtF,MAAMI,SAAS,MAAMH;YACrBR,OAAOW,OAAOC,IAAI,EAAEC,IAAI,CAAC;YACzBb,OAAOW,OAAOG,KAAK,EAAED,IAAI,CAACN;YAE1BH,OAAOW,IAAI;QACb;QAEAd,GAAG,sDAAsD;YACvD,MAAMG,SAAS,IAAID,eAAe;gBAAEE,MAAM;gBAAMC,WAAW;YAAK;YAChE,MAAMC,gBAAgB;YAEtB,MAAMC,kBAAkBJ,OAAOK,eAAe,CAACF;YAE/C,mBAAmB;YACnB,MAAMS,eAAeN,MACnB,CAAC,mEAAmE,CAAC;YAGvE,MAAMV,OAAOQ,iBAAiBS,OAAO,CAACC,OAAO,CAAChB;YAC9C,MAAMF,OAAOQ,iBAAiBS,OAAO,CAACC,OAAO,CAAC;YAE9C,6BAA6B;YAC7B,MAAMF;YAENZ,OAAOW,IAAI;QACb;QAEAd,GAAG,mDAAmD;YACpD,MAAMG,SAAS,IAAID,eAAe;gBAAEE,MAAM;gBAAMC,WAAW;YAAK;YAChE,MAAMC,gBAAgB;YAEtB,MAAMC,kBAAkBJ,OAAOK,eAAe,CAACF;YAE/C,mBAAmB;YACnB,MAAMS,eAAeN,MACnB,CAAC,gFAAgF,CAAC;YAGpF,MAAMV,OAAOQ,iBAAiBS,OAAO,CAACC,OAAO,CAAChB;YAC9C,MAAMF,OAAOQ,iBAAiBS,OAAO,CAACC,OAAO,CAAC;YAE9C,6BAA6B;YAC7B,MAAMF;YAENZ,OAAOW,IAAI;QACb;QAEAd,GAAG,+CAA+C;YAChD,MAAMG,SAAS,IAAID,eAAe;gBAAEE,MAAM;gBAAMC,WAAW;YAAI;YAC/D,MAAMC,gBAAgB;YAEtB,MAAMC,kBAAkBJ,OAAOK,eAAe,CAACF;YAE/C,uCAAuC;YACvC,MAAMP,OAAOQ,iBAAiBS,OAAO,CAACC,OAAO,CAAChB;YAC9C,MAAMF,OAAOQ,iBAAiBS,OAAO,CAACC,OAAO,CAAC;YAE9Cd,OAAOW,IAAI;QACb,GAAG;QAEHd,GAAG,4CAA4C;YAC7C,MAAMG,SAAS,IAAID,eAAe;gBAAEE,MAAM;gBAAMC,WAAW;YAAI;YAC/D,MAAMC,gBAAgB;YAEtB,eAAe;YACf,MAAMC,kBAAkBJ,OAAOK,eAAe,CAACF,eAAeY,KAAK,CAAC;YAClE,uBAAuB;YACzB;YAEA,iCAAiC;YACjC,MAAM,IAAIC,QAAQ,CAACC,UAAYC,WAAWD,SAAS;YAEnD,2BAA2B;YAC3B,MAAME,WAAW,MAAMb,MAAM;YAC7BV,OAAOuB,SAASC,MAAM,EAAEX,IAAI,CAAC;YAE7B,WAAW;YACXT,OAAOW,IAAI;YAEX,+BAA+B;YAC/B,MAAMP;QACR,GAAG;IACL;AACF"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=crypto-utils.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"crypto-utils.spec.d.ts","sourceRoot":"","sources":["../../src/auth/crypto-utils.spec.ts"],"names":[],"mappings":""}
@@ -1,36 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { deriveEncryptionKey } from './crypto-utils.js';
3
- describe('crypto-utils', ()=>{
4
- describe('deriveEncryptionKey', ()=>{
5
- it('should return the same key on multiple calls (deterministic)', ()=>{
6
- const key1 = deriveEncryptionKey();
7
- const key2 = deriveEncryptionKey();
8
- const key3 = deriveEncryptionKey();
9
- expect(key1).toBe(key2);
10
- expect(key2).toBe(key3);
11
- });
12
- it('should produce keys suitable for AES-256 encryption', ()=>{
13
- const key = deriveEncryptionKey();
14
- // AES-256 requires 256 bits = 32 bytes = 64 hex characters
15
- expect(key.length).toBe(64);
16
- // Should be valid hex (can be converted to Buffer)
17
- expect(()=>Buffer.from(key, 'hex')).not.toThrow();
18
- const buffer = Buffer.from(key, 'hex');
19
- expect(buffer.length).toBe(32); // 32 bytes
20
- });
21
- it('should complete key derivation in reasonable time', ()=>{
22
- // Test that 100k PBKDF2 iterations complete quickly enough for CLI use
23
- const startTime = Date.now();
24
- // Run multiple times to get average
25
- for(let i = 0; i < 5; i++){
26
- deriveEncryptionKey();
27
- }
28
- const endTime = Date.now();
29
- const avgTime = (endTime - startTime) / 5;
30
- // Each call should take less than 2 seconds on average
31
- expect(avgTime).toBeLessThan(2000);
32
- });
33
- });
34
- });
35
-
36
- //# sourceMappingURL=crypto-utils.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/auth/crypto-utils.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { deriveEncryptionKey } from './crypto-utils.js'\n\ndescribe('crypto-utils', () => {\n describe('deriveEncryptionKey', () => {\n it('should return the same key on multiple calls (deterministic)', () => {\n const key1 = deriveEncryptionKey()\n const key2 = deriveEncryptionKey()\n const key3 = deriveEncryptionKey()\n\n expect(key1).toBe(key2)\n expect(key2).toBe(key3)\n })\n\n it('should produce keys suitable for AES-256 encryption', () => {\n const key = deriveEncryptionKey()\n\n // AES-256 requires 256 bits = 32 bytes = 64 hex characters\n expect(key.length).toBe(64)\n\n // Should be valid hex (can be converted to Buffer)\n expect(() => Buffer.from(key, 'hex')).not.toThrow()\n\n const buffer = Buffer.from(key, 'hex')\n expect(buffer.length).toBe(32) // 32 bytes\n })\n\n it('should complete key derivation in reasonable time', () => {\n // Test that 100k PBKDF2 iterations complete quickly enough for CLI use\n const startTime = Date.now()\n\n // Run multiple times to get average\n for (let i = 0; i < 5; i++) {\n deriveEncryptionKey()\n }\n\n const endTime = Date.now()\n const avgTime = (endTime - startTime) / 5\n\n // Each call should take less than 2 seconds on average\n expect(avgTime).toBeLessThan(2000)\n })\n })\n})\n"],"names":["describe","expect","it","deriveEncryptionKey","key1","key2","key3","toBe","key","length","Buffer","from","not","toThrow","buffer","startTime","Date","now","i","endTime","avgTime","toBeLessThan"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,mBAAmB,QAAQ,oBAAmB;AAEvDH,SAAS,gBAAgB;IACvBA,SAAS,uBAAuB;QAC9BE,GAAG,gEAAgE;YACjE,MAAME,OAAOD;YACb,MAAME,OAAOF;YACb,MAAMG,OAAOH;YAEbF,OAAOG,MAAMG,IAAI,CAACF;YAClBJ,OAAOI,MAAME,IAAI,CAACD;QACpB;QAEAJ,GAAG,uDAAuD;YACxD,MAAMM,MAAML;YAEZ,2DAA2D;YAC3DF,OAAOO,IAAIC,MAAM,EAAEF,IAAI,CAAC;YAExB,mDAAmD;YACnDN,OAAO,IAAMS,OAAOC,IAAI,CAACH,KAAK,QAAQI,GAAG,CAACC,OAAO;YAEjD,MAAMC,SAASJ,OAAOC,IAAI,CAACH,KAAK;YAChCP,OAAOa,OAAOL,MAAM,EAAEF,IAAI,CAAC,KAAI,WAAW;QAC5C;QAEAL,GAAG,qDAAqD;YACtD,uEAAuE;YACvE,MAAMa,YAAYC,KAAKC,GAAG;YAE1B,oCAAoC;YACpC,IAAK,IAAIC,IAAI,GAAGA,IAAI,GAAGA,IAAK;gBAC1Bf;YACF;YAEA,MAAMgB,UAAUH,KAAKC,GAAG;YACxB,MAAMG,UAAU,AAACD,CAAAA,UAAUJ,SAAQ,IAAK;YAExC,uDAAuD;YACvDd,OAAOmB,SAASC,YAAY,CAAC;QAC/B;IACF;AACF"}
@@ -1,10 +0,0 @@
1
- /**
2
- * Unit tests for JWT validator
3
- *
4
- * Tests our wrapper logic around jose's JWT validation:
5
- * - Cache management (clearJWKSCache)
6
- * - Environment-based JWKS URI routing
7
- * - Error mapping from jose errors to our custom error codes
8
- */
9
- export {};
10
- //# sourceMappingURL=jwt-validator.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jwt-validator.spec.d.ts","sourceRoot":"","sources":["../../src/auth/jwt-validator.spec.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -1,236 +0,0 @@
1
- /**
2
- * Unit tests for JWT validator
3
- *
4
- * Tests our wrapper logic around jose's JWT validation:
5
- * - Cache management (clearJWKSCache)
6
- * - Environment-based JWKS URI routing
7
- * - Error mapping from jose errors to our custom error codes
8
- */ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
9
- import { clearJWKSCache, JWTValidationError, validateProjectToken } from './jwt-validator.js';
10
- // Helper to create a simple test JWT (will fail validation but tests the flow)
11
- function createTestJWT(payload, kid = 'test-key-id') {
12
- const header = Buffer.from(JSON.stringify({
13
- alg: 'RS256',
14
- kid,
15
- typ: 'JWT'
16
- })).toString('base64url');
17
- const payloadStr = Buffer.from(JSON.stringify(payload)).toString('base64url');
18
- const signature = 'fake_signature';
19
- return `${header}.${payloadStr}.${signature}`;
20
- }
21
- describe('JWT Validator', ()=>{
22
- // Mock JWKS with RSA key
23
- const mockJWKS = {
24
- keys: [
25
- {
26
- alg: 'RS256',
27
- e: 'AQAB',
28
- kid: 'test-key-id',
29
- kty: 'RSA',
30
- n: 'xGOr-H7A-PWO8VcD4sqDpCciAuqYDPq8zKWb4Vh6YhP8Ny3KcJaJhLMDEBJB3fKVvT-pPlkHPFBv7L7iHzRrJMXz8uDJVK-FTYmTQhcvKPyMWUDGDPNlVXEGkBLdj3DZqKjJ8iVChSh5DzKJvzr-RyGnH8Z7nLqBa91zxWfm7ztJxqP0qPRKz6vb4h8QyN-5X4Gh8gU7ZcLLnqLqJ6FhPvqKVcBhfN3KjM6h8hLXz6pPzKqJ8z6r8-9KcZXlWvR',
31
- use: 'sig'
32
- }
33
- ]
34
- };
35
- beforeEach(()=>{
36
- clearJWKSCache();
37
- vi.restoreAllMocks();
38
- });
39
- afterEach(()=>{
40
- clearJWKSCache();
41
- });
42
- describe('Cache Management', ()=>{
43
- it('should clear resolver cache when clearJWKSCache is called', async ()=>{
44
- const fetchMock = vi.fn().mockResolvedValue({
45
- json: ()=>Promise.resolve(mockJWKS),
46
- ok: true,
47
- status: 200
48
- });
49
- global.fetch = fetchMock;
50
- const token = createTestJWT({
51
- exp: Math.floor(Date.now() / 1000) + 3600
52
- });
53
- // First validation - creates and caches resolver
54
- try {
55
- await validateProjectToken(token, 'staging');
56
- } catch (_error) {
57
- // Expected to fail on signature
58
- }
59
- const firstCallCount = fetchMock.mock.calls.length;
60
- expect(firstCallCount).toBeGreaterThanOrEqual(1);
61
- // Clear the cache - this is OUR logic
62
- clearJWKSCache();
63
- // Second validation after clearing cache - should create new resolver
64
- try {
65
- await validateProjectToken(token, 'staging');
66
- } catch (_error) {
67
- // Expected to fail on signature
68
- }
69
- // Verify fetch was called again after cache clear
70
- expect(fetchMock.mock.calls.length).toBeGreaterThan(firstCallCount);
71
- });
72
- });
73
- describe('Error Code Mapping', ()=>{
74
- it('should map network errors to JWKS_FETCH_FAILED code', async ()=>{
75
- global.fetch = vi.fn().mockRejectedValue(new Error('ENOTFOUND'));
76
- const token = createTestJWT({
77
- exp: Math.floor(Date.now() / 1000) + 3600
78
- });
79
- try {
80
- await validateProjectToken(token, 'staging');
81
- expect.fail('Should have thrown an error');
82
- } catch (error) {
83
- expect(error).toBeInstanceOf(JWTValidationError);
84
- if (error instanceof JWTValidationError) {
85
- // Verify our error mapping logic
86
- expect(error.code).toBe('JWKS_FETCH_FAILED');
87
- expect(error.message).toContain('Failed to fetch JWKS');
88
- }
89
- }
90
- });
91
- it('should map jose signature errors to SIGNATURE_INVALID code', async ()=>{
92
- global.fetch = vi.fn().mockResolvedValue({
93
- json: ()=>Promise.resolve(mockJWKS),
94
- ok: true,
95
- status: 200
96
- });
97
- const badToken = 'eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3Qta2V5LWlkIn0.e30.bad_signature';
98
- try {
99
- await validateProjectToken(badToken, 'staging');
100
- expect.fail('Should have thrown an error');
101
- } catch (error) {
102
- expect(error).toBeInstanceOf(JWTValidationError);
103
- if (error instanceof JWTValidationError) {
104
- // Verify our error mapping logic - invalid tokens may fail at different stages
105
- // The important thing is that signature-related errors map to either SIGNATURE_INVALID or MISSING_KID
106
- expect([
107
- 'SIGNATURE_INVALID',
108
- 'MISSING_KID'
109
- ]).toContain(error.code);
110
- }
111
- }
112
- });
113
- it('should map expired token errors to EXPIRED code', async ()=>{
114
- global.fetch = vi.fn().mockResolvedValue({
115
- json: ()=>Promise.resolve(mockJWKS),
116
- ok: true,
117
- status: 200
118
- });
119
- // Create token that expired 1 hour ago
120
- const expiredToken = createTestJWT({
121
- exp: Math.floor(Date.now() / 1000) - 3600,
122
- iat: Math.floor(Date.now() / 1000) - 7200
123
- });
124
- try {
125
- await validateProjectToken(expiredToken, 'staging');
126
- expect.fail('Should have thrown an error');
127
- } catch (error) {
128
- expect(error).toBeInstanceOf(JWTValidationError);
129
- if (error instanceof JWTValidationError) {
130
- // Verify our error mapping logic
131
- // Note: Mock tokens with bad signatures may fail signature validation before expiry check
132
- // In real scenarios with valid signatures, EXPIRED would be returned
133
- expect([
134
- 'EXPIRED',
135
- 'SIGNATURE_INVALID',
136
- 'MISSING_KID'
137
- ]).toContain(error.code);
138
- }
139
- }
140
- });
141
- it('should map missing kid errors to MISSING_KID code', async ()=>{
142
- global.fetch = vi.fn().mockResolvedValue({
143
- json: ()=>Promise.resolve(mockJWKS),
144
- ok: true,
145
- status: 200
146
- });
147
- // Create token without kid in header
148
- const header = Buffer.from(JSON.stringify({
149
- alg: 'RS256',
150
- typ: 'JWT'
151
- })).toString('base64url');
152
- const payload = Buffer.from(JSON.stringify({
153
- exp: Math.floor(Date.now() / 1000) + 3600
154
- })).toString('base64url');
155
- const tokenWithoutKid = `${header}.${payload}.fake_signature`;
156
- try {
157
- await validateProjectToken(tokenWithoutKid, 'staging');
158
- expect.fail('Should have thrown an error');
159
- } catch (error) {
160
- expect(error).toBeInstanceOf(JWTValidationError);
161
- if (error instanceof JWTValidationError) {
162
- // Verify our error mapping logic - tokens without kid may fail at various stages
163
- expect([
164
- 'MISSING_KID',
165
- 'SIGNATURE_INVALID'
166
- ]).toContain(error.code);
167
- }
168
- }
169
- });
170
- it('should map no matching key errors to SIGNATURE_INVALID code', async ()=>{
171
- global.fetch = vi.fn().mockResolvedValue({
172
- json: ()=>Promise.resolve(mockJWKS),
173
- ok: true,
174
- status: 200
175
- });
176
- // Create token with a kid that doesn't exist in JWKS
177
- const tokenWithWrongKid = createTestJWT({
178
- exp: Math.floor(Date.now() / 1000) + 3600
179
- }, 'non-existent-key-id');
180
- try {
181
- await validateProjectToken(tokenWithWrongKid, 'staging');
182
- expect.fail('Should have thrown an error');
183
- } catch (error) {
184
- expect(error).toBeInstanceOf(JWTValidationError);
185
- if (error instanceof JWTValidationError) {
186
- // Verify our error mapping logic
187
- expect(error.code).toBe('SIGNATURE_INVALID');
188
- expect(error.message).toContain('Key not found in JWKS');
189
- }
190
- }
191
- });
192
- it('should handle multiple network error formats', async ()=>{
193
- const networkErrors = [
194
- new Error('fetch failed'),
195
- new Error('network error'),
196
- new Error('ECONNREFUSED')
197
- ];
198
- for (const networkError of networkErrors){
199
- clearJWKSCache();
200
- global.fetch = vi.fn().mockRejectedValue(networkError);
201
- const token = createTestJWT({
202
- exp: Math.floor(Date.now() / 1000) + 3600
203
- });
204
- try {
205
- await validateProjectToken(token, 'staging');
206
- expect.fail('Should have thrown an error');
207
- } catch (error) {
208
- expect(error).toBeInstanceOf(JWTValidationError);
209
- if (error instanceof JWTValidationError) {
210
- expect(error.code).toBe('JWKS_FETCH_FAILED');
211
- }
212
- }
213
- }
214
- });
215
- it('should handle generic errors with fallback', async ()=>{
216
- // Mock an unexpected error type
217
- global.fetch = vi.fn().mockRejectedValue('string error');
218
- const token = createTestJWT({
219
- exp: Math.floor(Date.now() / 1000) + 3600
220
- });
221
- try {
222
- await validateProjectToken(token, 'staging');
223
- expect.fail('Should have thrown an error');
224
- } catch (error) {
225
- expect(error).toBeInstanceOf(JWTValidationError);
226
- if (error instanceof JWTValidationError) {
227
- // Generic errors fall back to SIGNATURE_INVALID
228
- expect(error.code).toBe('SIGNATURE_INVALID');
229
- expect(error.message).toContain('JWT validation failed');
230
- }
231
- }
232
- });
233
- });
234
- });
235
-
236
- //# sourceMappingURL=jwt-validator.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/auth/jwt-validator.spec.ts"],"sourcesContent":["/**\n * Unit tests for JWT validator\n *\n * Tests our wrapper logic around jose's JWT validation:\n * - Cache management (clearJWKSCache)\n * - Environment-based JWKS URI routing\n * - Error mapping from jose errors to our custom error codes\n */\n\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport { clearJWKSCache, JWTValidationError, validateProjectToken } from './jwt-validator.js'\n\n// Helper to create a simple test JWT (will fail validation but tests the flow)\nfunction createTestJWT(payload: Record<string, unknown>, kid = 'test-key-id'): string {\n const header = Buffer.from(JSON.stringify({ alg: 'RS256', kid, typ: 'JWT' })).toString(\n 'base64url',\n )\n const payloadStr = Buffer.from(JSON.stringify(payload)).toString('base64url')\n const signature = 'fake_signature'\n return `${header}.${payloadStr}.${signature}`\n}\n\ndescribe('JWT Validator', () => {\n // Mock JWKS with RSA key\n const mockJWKS = {\n keys: [\n {\n alg: 'RS256',\n e: 'AQAB',\n kid: 'test-key-id',\n kty: 'RSA',\n n: 'xGOr-H7A-PWO8VcD4sqDpCciAuqYDPq8zKWb4Vh6YhP8Ny3KcJaJhLMDEBJB3fKVvT-pPlkHPFBv7L7iHzRrJMXz8uDJVK-FTYmTQhcvKPyMWUDGDPNlVXEGkBLdj3DZqKjJ8iVChSh5DzKJvzr-RyGnH8Z7nLqBa91zxWfm7ztJxqP0qPRKz6vb4h8QyN-5X4Gh8gU7ZcLLnqLqJ6FhPvqKVcBhfN3KjM6h8hLXz6pPzKqJ8z6r8-9KcZXlWvR',\n use: 'sig',\n },\n ],\n }\n\n beforeEach(() => {\n clearJWKSCache()\n vi.restoreAllMocks()\n })\n\n afterEach(() => {\n clearJWKSCache()\n })\n\n describe('Cache Management', () => {\n it('should clear resolver cache when clearJWKSCache is called', async () => {\n const fetchMock = vi.fn().mockResolvedValue({\n json: () => Promise.resolve(mockJWKS),\n ok: true,\n status: 200,\n })\n global.fetch = fetchMock\n\n const token = createTestJWT({ exp: Math.floor(Date.now() / 1000) + 3600 })\n\n // First validation - creates and caches resolver\n try {\n await validateProjectToken(token, 'staging')\n } catch (_error) {\n // Expected to fail on signature\n }\n\n const firstCallCount = fetchMock.mock.calls.length\n expect(firstCallCount).toBeGreaterThanOrEqual(1)\n\n // Clear the cache - this is OUR logic\n clearJWKSCache()\n\n // Second validation after clearing cache - should create new resolver\n try {\n await validateProjectToken(token, 'staging')\n } catch (_error) {\n // Expected to fail on signature\n }\n\n // Verify fetch was called again after cache clear\n expect(fetchMock.mock.calls.length).toBeGreaterThan(firstCallCount)\n })\n })\n\n describe('Error Code Mapping', () => {\n it('should map network errors to JWKS_FETCH_FAILED code', async () => {\n global.fetch = vi.fn().mockRejectedValue(new Error('ENOTFOUND'))\n\n const token = createTestJWT({ exp: Math.floor(Date.now() / 1000) + 3600 })\n\n try {\n await validateProjectToken(token, 'staging')\n expect.fail('Should have thrown an error')\n } catch (error) {\n expect(error).toBeInstanceOf(JWTValidationError)\n if (error instanceof JWTValidationError) {\n // Verify our error mapping logic\n expect(error.code).toBe('JWKS_FETCH_FAILED')\n expect(error.message).toContain('Failed to fetch JWKS')\n }\n }\n })\n\n it('should map jose signature errors to SIGNATURE_INVALID code', async () => {\n global.fetch = vi.fn().mockResolvedValue({\n json: () => Promise.resolve(mockJWKS),\n ok: true,\n status: 200,\n })\n\n const badToken = 'eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3Qta2V5LWlkIn0.e30.bad_signature'\n\n try {\n await validateProjectToken(badToken, 'staging')\n expect.fail('Should have thrown an error')\n } catch (error) {\n expect(error).toBeInstanceOf(JWTValidationError)\n if (error instanceof JWTValidationError) {\n // Verify our error mapping logic - invalid tokens may fail at different stages\n // The important thing is that signature-related errors map to either SIGNATURE_INVALID or MISSING_KID\n expect(['SIGNATURE_INVALID', 'MISSING_KID']).toContain(error.code)\n }\n }\n })\n\n it('should map expired token errors to EXPIRED code', async () => {\n global.fetch = vi.fn().mockResolvedValue({\n json: () => Promise.resolve(mockJWKS),\n ok: true,\n status: 200,\n })\n\n // Create token that expired 1 hour ago\n const expiredToken = createTestJWT({\n exp: Math.floor(Date.now() / 1000) - 3600,\n iat: Math.floor(Date.now() / 1000) - 7200,\n })\n\n try {\n await validateProjectToken(expiredToken, 'staging')\n expect.fail('Should have thrown an error')\n } catch (error) {\n expect(error).toBeInstanceOf(JWTValidationError)\n if (error instanceof JWTValidationError) {\n // Verify our error mapping logic\n // Note: Mock tokens with bad signatures may fail signature validation before expiry check\n // In real scenarios with valid signatures, EXPIRED would be returned\n expect(['EXPIRED', 'SIGNATURE_INVALID', 'MISSING_KID']).toContain(error.code)\n }\n }\n })\n\n it('should map missing kid errors to MISSING_KID code', async () => {\n global.fetch = vi.fn().mockResolvedValue({\n json: () => Promise.resolve(mockJWKS),\n ok: true,\n status: 200,\n })\n\n // Create token without kid in header\n const header = Buffer.from(JSON.stringify({ alg: 'RS256', typ: 'JWT' })).toString('base64url')\n const payload = Buffer.from(\n JSON.stringify({ exp: Math.floor(Date.now() / 1000) + 3600 }),\n ).toString('base64url')\n const tokenWithoutKid = `${header}.${payload}.fake_signature`\n\n try {\n await validateProjectToken(tokenWithoutKid, 'staging')\n expect.fail('Should have thrown an error')\n } catch (error) {\n expect(error).toBeInstanceOf(JWTValidationError)\n if (error instanceof JWTValidationError) {\n // Verify our error mapping logic - tokens without kid may fail at various stages\n expect(['MISSING_KID', 'SIGNATURE_INVALID']).toContain(error.code)\n }\n }\n })\n\n it('should map no matching key errors to SIGNATURE_INVALID code', async () => {\n global.fetch = vi.fn().mockResolvedValue({\n json: () => Promise.resolve(mockJWKS),\n ok: true,\n status: 200,\n })\n\n // Create token with a kid that doesn't exist in JWKS\n const tokenWithWrongKid = createTestJWT(\n { exp: Math.floor(Date.now() / 1000) + 3600 },\n 'non-existent-key-id',\n )\n\n try {\n await validateProjectToken(tokenWithWrongKid, 'staging')\n expect.fail('Should have thrown an error')\n } catch (error) {\n expect(error).toBeInstanceOf(JWTValidationError)\n if (error instanceof JWTValidationError) {\n // Verify our error mapping logic\n expect(error.code).toBe('SIGNATURE_INVALID')\n expect(error.message).toContain('Key not found in JWKS')\n }\n }\n })\n\n it('should handle multiple network error formats', async () => {\n const networkErrors = [\n new Error('fetch failed'),\n new Error('network error'),\n new Error('ECONNREFUSED'),\n ]\n\n for (const networkError of networkErrors) {\n clearJWKSCache()\n global.fetch = vi.fn().mockRejectedValue(networkError)\n\n const token = createTestJWT({ exp: Math.floor(Date.now() / 1000) + 3600 })\n\n try {\n await validateProjectToken(token, 'staging')\n expect.fail('Should have thrown an error')\n } catch (error) {\n expect(error).toBeInstanceOf(JWTValidationError)\n if (error instanceof JWTValidationError) {\n expect(error.code).toBe('JWKS_FETCH_FAILED')\n }\n }\n }\n })\n\n it('should handle generic errors with fallback', async () => {\n // Mock an unexpected error type\n global.fetch = vi.fn().mockRejectedValue('string error')\n\n const token = createTestJWT({ exp: Math.floor(Date.now() / 1000) + 3600 })\n\n try {\n await validateProjectToken(token, 'staging')\n expect.fail('Should have thrown an error')\n } catch (error) {\n expect(error).toBeInstanceOf(JWTValidationError)\n if (error instanceof JWTValidationError) {\n // Generic errors fall back to SIGNATURE_INVALID\n expect(error.code).toBe('SIGNATURE_INVALID')\n expect(error.message).toContain('JWT validation failed')\n }\n }\n })\n })\n})\n"],"names":["afterEach","beforeEach","describe","expect","it","vi","clearJWKSCache","JWTValidationError","validateProjectToken","createTestJWT","payload","kid","header","Buffer","from","JSON","stringify","alg","typ","toString","payloadStr","signature","mockJWKS","keys","e","kty","n","use","restoreAllMocks","fetchMock","fn","mockResolvedValue","json","Promise","resolve","ok","status","global","fetch","token","exp","Math","floor","Date","now","_error","firstCallCount","mock","calls","length","toBeGreaterThanOrEqual","toBeGreaterThan","mockRejectedValue","Error","fail","error","toBeInstanceOf","code","toBe","message","toContain","badToken","expiredToken","iat","tokenWithoutKid","tokenWithWrongKid","networkErrors","networkError"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=oauth-flow.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"oauth-flow.spec.d.ts","sourceRoot":"","sources":["../../src/auth/oauth-flow.spec.ts"],"names":[],"mappings":""}
@@ -1,134 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from 'vitest';
2
- import { CallbackServer } from './callback-server.js';
3
- import { executeOAuthFlow, getValidAccessToken, OAuthFlowError } from './oauth-flow.js';
4
- import { refreshAccessToken } from './refresh.js';
5
- import { TokenStore } from './token-store.js';
6
- // Mock the refresh module
7
- vi.mock('./refresh.js', ()=>({
8
- exchangeCodeForTokens: vi.fn(),
9
- refreshAccessToken: vi.fn()
10
- }));
11
- // Mock browser and callback server
12
- vi.mock('./browser.js', ()=>({
13
- buildAuthorizationUrl: vi.fn(()=>'https://www.figma.com/oauth?...'),
14
- openBrowser: vi.fn()
15
- }));
16
- // Mock @clack/prompts
17
- vi.mock('@clack/prompts', ()=>({
18
- confirm: vi.fn().mockResolvedValue(true),
19
- isCancel: vi.fn().mockReturnValue(false)
20
- }));
21
- // Create mock factory for CallbackServer
22
- const createMockCallbackServer = ()=>{
23
- const mock = {
24
- getActualPort: vi.fn().mockReturnValue(3000),
25
- stop: vi.fn(),
26
- waitForCallback: vi.fn()
27
- };
28
- return mock;
29
- };
30
- vi.mock('./callback-server.js', ()=>({
31
- CallbackServer: vi.fn()
32
- }));
33
- describe('oauth-flow', ()=>{
34
- describe('getValidAccessToken', ()=>{
35
- let tokenStore;
36
- beforeEach(()=>{
37
- tokenStore = new TokenStore({
38
- configName: 'test-payloadcms-figma-oauth-flow'
39
- });
40
- tokenStore.clearTokens();
41
- });
42
- it('should return access token if valid tokens exist', async ()=>{
43
- const mockTokens = {
44
- accessToken: 'valid-token',
45
- expiresAt: Date.now() + 3600000,
46
- refreshToken: 'refresh-token'
47
- };
48
- tokenStore.setTokens(mockTokens);
49
- const token = await getValidAccessToken(tokenStore);
50
- expect(token).toBe('valid-token');
51
- });
52
- it('should refresh expired tokens', async ()=>{
53
- const expiredTokens = {
54
- accessToken: 'expired-token',
55
- expiresAt: Date.now() - 1000,
56
- refreshToken: 'refresh-token'
57
- };
58
- tokenStore.setTokens(expiredTokens);
59
- const newTokens = {
60
- accessToken: 'new-token',
61
- expiresAt: Date.now() + 3600000,
62
- refreshToken: 'new-refresh-token'
63
- };
64
- // Mock the refresh function
65
- vi.mocked(refreshAccessToken).mockResolvedValueOnce(newTokens);
66
- const token = await getValidAccessToken(tokenStore);
67
- expect(token).toBe('new-token');
68
- // Verify tokens were stored
69
- const storedTokens = tokenStore.getTokens();
70
- expect(storedTokens?.accessToken).toBe('new-token');
71
- });
72
- it('should clear tokens and throw on refresh failure', async ()=>{
73
- const expiredTokens = {
74
- accessToken: 'expired-token',
75
- expiresAt: Date.now() - 1000,
76
- refreshToken: 'refresh-token'
77
- };
78
- tokenStore.setTokens(expiredTokens);
79
- // Mock refresh to fail
80
- vi.mocked(refreshAccessToken).mockRejectedValueOnce(new Error('Refresh failed'));
81
- await expect(getValidAccessToken(tokenStore)).rejects.toThrow(OAuthFlowError);
82
- // Verify tokens were cleared
83
- expect(tokenStore.getTokens()).toBeNull();
84
- });
85
- });
86
- describe('executeOAuthFlow', ()=>{
87
- let tokenStore;
88
- let mockServer;
89
- beforeEach(()=>{
90
- tokenStore = new TokenStore({
91
- configName: 'test-payloadcms-figma-oauth-execute'
92
- });
93
- tokenStore.clearTokens();
94
- vi.clearAllMocks();
95
- // Setup mock server with default pending callback
96
- mockServer = createMockCallbackServer();
97
- mockServer.waitForCallback.mockReturnValue(new Promise(()=>{
98
- /* pending forever by default */ }));
99
- vi.mocked(CallbackServer).mockImplementation(()=>mockServer);
100
- });
101
- it('should execute mock OAuth flow successfully (default behavior)', async ()=>{
102
- const result = await executeOAuthFlow(tokenStore);
103
- // Verify mock tokens were generated and stored
104
- const storedTokens = tokenStore.getTokens();
105
- expect(storedTokens).toBeDefined();
106
- expect(storedTokens?.accessToken).toMatch(/^figt_mock_access_token_/);
107
- expect(storedTokens?.refreshToken).toMatch(/^figt_mock_refresh_token_/);
108
- expect(storedTokens?.tokenType).toBe('Bearer');
109
- expect(storedTokens?.expiresAt).toBeGreaterThan(Date.now());
110
- // Verify result
111
- expect(result.tokens).toEqual(storedTokens);
112
- expect(result.userId).toBe('mock_user_123');
113
- // Verify callback server was NOT started (mock flow skips it)
114
- expect(mockServer.waitForCallback).not.toHaveBeenCalled();
115
- });
116
- it('should handle callback timeout (real OAuth flow)', async ()=>{
117
- // Temporarily disable mocking to test real OAuth flow error handling
118
- const originalEnv = process.env.FIGMA_MOCK_OAUTH;
119
- process.env.FIGMA_MOCK_OAUTH = 'false';
120
- mockServer.waitForCallback.mockRejectedValueOnce(new Error('Callback timed out'));
121
- await expect(executeOAuthFlow(tokenStore)).rejects.toThrow(OAuthFlowError);
122
- // Server should be stopped
123
- expect(mockServer.stop).toHaveBeenCalled();
124
- // Restore original environment
125
- if (originalEnv === undefined) {
126
- delete process.env.FIGMA_MOCK_OAUTH;
127
- } else {
128
- process.env.FIGMA_MOCK_OAUTH = originalEnv;
129
- }
130
- });
131
- });
132
- });
133
-
134
- //# sourceMappingURL=oauth-flow.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/auth/oauth-flow.spec.ts"],"sourcesContent":["import { beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport type { FigmaTokens } from './types.js'\n\nimport { CallbackServer } from './callback-server.js'\nimport { executeOAuthFlow, getValidAccessToken, OAuthFlowError } from './oauth-flow.js'\nimport { refreshAccessToken } from './refresh.js'\nimport { TokenStore } from './token-store.js'\n\n// Mock the refresh module\nvi.mock('./refresh.js', () => ({\n exchangeCodeForTokens: vi.fn(),\n refreshAccessToken: vi.fn(),\n}))\n\n// Mock browser and callback server\nvi.mock('./browser.js', () => ({\n buildAuthorizationUrl: vi.fn(() => 'https://www.figma.com/oauth?...'),\n openBrowser: vi.fn(),\n}))\n\n// Mock @clack/prompts\nvi.mock('@clack/prompts', () => ({\n confirm: vi.fn().mockResolvedValue(true),\n isCancel: vi.fn().mockReturnValue(false),\n}))\n\n// Create mock factory for CallbackServer\nconst createMockCallbackServer = () => {\n const mock = {\n getActualPort: vi.fn().mockReturnValue(3000),\n stop: vi.fn(),\n waitForCallback: vi.fn(),\n }\n return mock\n}\n\nvi.mock('./callback-server.js', () => ({\n CallbackServer: vi.fn(),\n}))\n\ndescribe('oauth-flow', () => {\n describe('getValidAccessToken', () => {\n let tokenStore: TokenStore\n\n beforeEach(() => {\n tokenStore = new TokenStore({ configName: 'test-payloadcms-figma-oauth-flow' })\n tokenStore.clearTokens()\n })\n\n it('should return access token if valid tokens exist', async () => {\n const mockTokens: FigmaTokens = {\n accessToken: 'valid-token',\n expiresAt: Date.now() + 3600000, // 1 hour from now\n refreshToken: 'refresh-token',\n }\n\n tokenStore.setTokens(mockTokens)\n\n const token = await getValidAccessToken(tokenStore)\n expect(token).toBe('valid-token')\n })\n\n it('should refresh expired tokens', async () => {\n const expiredTokens: FigmaTokens = {\n accessToken: 'expired-token',\n expiresAt: Date.now() - 1000, // Expired\n refreshToken: 'refresh-token',\n }\n\n tokenStore.setTokens(expiredTokens)\n\n const newTokens: FigmaTokens = {\n accessToken: 'new-token',\n expiresAt: Date.now() + 3600000,\n refreshToken: 'new-refresh-token',\n }\n\n // Mock the refresh function\n vi.mocked(refreshAccessToken).mockResolvedValueOnce(newTokens)\n\n const token = await getValidAccessToken(tokenStore)\n expect(token).toBe('new-token')\n\n // Verify tokens were stored\n const storedTokens = tokenStore.getTokens()\n expect(storedTokens?.accessToken).toBe('new-token')\n })\n\n it('should clear tokens and throw on refresh failure', async () => {\n const expiredTokens: FigmaTokens = {\n accessToken: 'expired-token',\n expiresAt: Date.now() - 1000,\n refreshToken: 'refresh-token',\n }\n\n tokenStore.setTokens(expiredTokens)\n\n // Mock refresh to fail\n vi.mocked(refreshAccessToken).mockRejectedValueOnce(new Error('Refresh failed'))\n\n await expect(getValidAccessToken(tokenStore)).rejects.toThrow(OAuthFlowError)\n\n // Verify tokens were cleared\n expect(tokenStore.getTokens()).toBeNull()\n })\n })\n\n describe('executeOAuthFlow', () => {\n let tokenStore: TokenStore\n let mockServer: ReturnType<typeof createMockCallbackServer>\n\n beforeEach(() => {\n tokenStore = new TokenStore({ configName: 'test-payloadcms-figma-oauth-execute' })\n tokenStore.clearTokens()\n vi.clearAllMocks()\n\n // Setup mock server with default pending callback\n mockServer = createMockCallbackServer()\n mockServer.waitForCallback.mockReturnValue(\n new Promise(() => {\n /* pending forever by default */\n }),\n )\n vi.mocked(CallbackServer).mockImplementation(() => mockServer as unknown as CallbackServer)\n })\n\n it('should execute mock OAuth flow successfully (default behavior)', async () => {\n const result = await executeOAuthFlow(tokenStore)\n\n // Verify mock tokens were generated and stored\n const storedTokens = tokenStore.getTokens()\n expect(storedTokens).toBeDefined()\n expect(storedTokens?.accessToken).toMatch(/^figt_mock_access_token_/)\n expect(storedTokens?.refreshToken).toMatch(/^figt_mock_refresh_token_/)\n expect(storedTokens?.tokenType).toBe('Bearer')\n expect(storedTokens?.expiresAt).toBeGreaterThan(Date.now())\n\n // Verify result\n expect(result.tokens).toEqual(storedTokens)\n expect(result.userId).toBe('mock_user_123')\n\n // Verify callback server was NOT started (mock flow skips it)\n expect(mockServer.waitForCallback).not.toHaveBeenCalled()\n })\n\n it('should handle callback timeout (real OAuth flow)', async () => {\n // Temporarily disable mocking to test real OAuth flow error handling\n const originalEnv = process.env.FIGMA_MOCK_OAUTH\n process.env.FIGMA_MOCK_OAUTH = 'false'\n\n mockServer.waitForCallback.mockRejectedValueOnce(new Error('Callback timed out'))\n\n await expect(executeOAuthFlow(tokenStore)).rejects.toThrow(OAuthFlowError)\n\n // Server should be stopped\n expect(mockServer.stop).toHaveBeenCalled()\n\n // Restore original environment\n if (originalEnv === undefined) {\n delete process.env.FIGMA_MOCK_OAUTH\n } else {\n process.env.FIGMA_MOCK_OAUTH = originalEnv\n }\n })\n })\n})\n"],"names":["beforeEach","describe","expect","it","vi","CallbackServer","executeOAuthFlow","getValidAccessToken","OAuthFlowError","refreshAccessToken","TokenStore","mock","exchangeCodeForTokens","fn","buildAuthorizationUrl","openBrowser","confirm","mockResolvedValue","isCancel","mockReturnValue","createMockCallbackServer","getActualPort","stop","waitForCallback","tokenStore","configName","clearTokens","mockTokens","accessToken","expiresAt","Date","now","refreshToken","setTokens","token","toBe","expiredTokens","newTokens","mocked","mockResolvedValueOnce","storedTokens","getTokens","mockRejectedValueOnce","Error","rejects","toThrow","toBeNull","mockServer","clearAllMocks","Promise","mockImplementation","result","toBeDefined","toMatch","tokenType","toBeGreaterThan","tokens","toEqual","userId","not","toHaveBeenCalled","originalEnv","process","env","FIGMA_MOCK_OAUTH","undefined"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=pkce.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pkce.spec.d.ts","sourceRoot":"","sources":["../../src/auth/pkce.spec.ts"],"names":[],"mappings":""}
@@ -1,32 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { generateCodeChallenge, generatePKCEPair } from './pkce.js';
3
- describe('generateCodeChallenge', ()=>{
4
- it('should generate consistent challenge for same verifier', ()=>{
5
- const verifier = 'test-verifier-123456789012345678901234567890';
6
- const challenge1 = generateCodeChallenge(verifier);
7
- const challenge2 = generateCodeChallenge(verifier);
8
- expect(challenge1).toBe(challenge2);
9
- });
10
- it('should generate different challenges for different verifiers', ()=>{
11
- const verifier1 = 'test-verifier-1';
12
- const verifier2 = 'test-verifier-2';
13
- const challenge1 = generateCodeChallenge(verifier1);
14
- const challenge2 = generateCodeChallenge(verifier2);
15
- expect(challenge1).not.toBe(challenge2);
16
- });
17
- });
18
- describe('generatePKCEPair', ()=>{
19
- it('should generate a complete PKCE pair', ()=>{
20
- const pair = generatePKCEPair();
21
- expect(pair).toHaveProperty('codeVerifier');
22
- expect(pair).toHaveProperty('codeChallenge');
23
- expect(pair).toHaveProperty('codeChallengeMethod');
24
- });
25
- it('should generate challenge derived from verifier', ()=>{
26
- const pair = generatePKCEPair();
27
- const derivedChallenge = generateCodeChallenge(pair.codeVerifier);
28
- expect(pair.codeChallenge).toBe(derivedChallenge);
29
- });
30
- });
31
-
32
- //# sourceMappingURL=pkce.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/auth/pkce.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { generateCodeChallenge, generatePKCEPair } from './pkce.js'\n\ndescribe('generateCodeChallenge', () => {\n it('should generate consistent challenge for same verifier', () => {\n const verifier = 'test-verifier-123456789012345678901234567890'\n const challenge1 = generateCodeChallenge(verifier)\n const challenge2 = generateCodeChallenge(verifier)\n expect(challenge1).toBe(challenge2)\n })\n\n it('should generate different challenges for different verifiers', () => {\n const verifier1 = 'test-verifier-1'\n const verifier2 = 'test-verifier-2'\n const challenge1 = generateCodeChallenge(verifier1)\n const challenge2 = generateCodeChallenge(verifier2)\n expect(challenge1).not.toBe(challenge2)\n })\n})\n\ndescribe('generatePKCEPair', () => {\n it('should generate a complete PKCE pair', () => {\n const pair = generatePKCEPair()\n\n expect(pair).toHaveProperty('codeVerifier')\n expect(pair).toHaveProperty('codeChallenge')\n expect(pair).toHaveProperty('codeChallengeMethod')\n })\n\n it('should generate challenge derived from verifier', () => {\n const pair = generatePKCEPair()\n const derivedChallenge = generateCodeChallenge(pair.codeVerifier)\n expect(pair.codeChallenge).toBe(derivedChallenge)\n })\n})\n"],"names":["describe","expect","it","generateCodeChallenge","generatePKCEPair","verifier","challenge1","challenge2","toBe","verifier1","verifier2","not","pair","toHaveProperty","derivedChallenge","codeVerifier","codeChallenge"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,qBAAqB,EAAEC,gBAAgB,QAAQ,YAAW;AAEnEJ,SAAS,yBAAyB;IAChCE,GAAG,0DAA0D;QAC3D,MAAMG,WAAW;QACjB,MAAMC,aAAaH,sBAAsBE;QACzC,MAAME,aAAaJ,sBAAsBE;QACzCJ,OAAOK,YAAYE,IAAI,CAACD;IAC1B;IAEAL,GAAG,gEAAgE;QACjE,MAAMO,YAAY;QAClB,MAAMC,YAAY;QAClB,MAAMJ,aAAaH,sBAAsBM;QACzC,MAAMF,aAAaJ,sBAAsBO;QACzCT,OAAOK,YAAYK,GAAG,CAACH,IAAI,CAACD;IAC9B;AACF;AAEAP,SAAS,oBAAoB;IAC3BE,GAAG,wCAAwC;QACzC,MAAMU,OAAOR;QAEbH,OAAOW,MAAMC,cAAc,CAAC;QAC5BZ,OAAOW,MAAMC,cAAc,CAAC;QAC5BZ,OAAOW,MAAMC,cAAc,CAAC;IAC9B;IAEAX,GAAG,mDAAmD;QACpD,MAAMU,OAAOR;QACb,MAAMU,mBAAmBX,sBAAsBS,KAAKG,YAAY;QAChEd,OAAOW,KAAKI,aAAa,EAAER,IAAI,CAACM;IAClC;AACF"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=project-token.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"project-token.spec.d.ts","sourceRoot":"","sources":["../../src/auth/project-token.spec.ts"],"names":[],"mappings":""}