@payloadcms/figma 0.0.1-alpha.7 → 0.0.1-alpha.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/control-plane.d.ts +56 -6
- package/dist/api/control-plane.js +181 -72
- package/dist/api/figma-api.d.ts +22 -1
- package/dist/api/figma-api.js +78 -25
- package/dist/auth/callback-server.d.ts +19 -7
- package/dist/auth/callback-server.js +72 -30
- package/dist/auth/credentials.d.ts +21 -0
- package/dist/auth/credentials.js +21 -0
- package/dist/auth/crypto-utils.d.ts +28 -0
- package/dist/auth/crypto-utils.js +132 -21
- package/dist/auth/jwt-validator.d.ts +2 -1
- package/dist/auth/jwt-validator.js +2 -2
- package/dist/auth/oauth-flow.d.ts +19 -3
- package/dist/auth/oauth-flow.js +77 -22
- package/dist/auth/project-token.d.ts +32 -16
- package/dist/auth/project-token.js +171 -65
- package/dist/auth/refresh.d.ts +2 -1
- package/dist/auth/refresh.js +25 -12
- package/dist/auth/token-store-migration.d.ts +58 -0
- package/dist/auth/token-store-migration.js +156 -0
- package/dist/auth/token-store.d.ts +63 -97
- package/dist/auth/token-store.js +405 -122
- package/dist/auth/types.d.ts +35 -4
- package/dist/cli.js +93 -6
- package/dist/commands/bootstrap.d.ts +18 -0
- package/dist/commands/bootstrap.js +90 -0
- package/dist/commands/build-lambda-zip.d.ts +5 -0
- package/dist/commands/build-lambda-zip.js +19 -0
- package/dist/commands/debug.d.ts +8 -0
- package/dist/commands/debug.js +180 -0
- package/dist/commands/deploy.d.ts +9 -0
- package/dist/commands/deploy.js +180 -151
- package/dist/commands/dump-tokens.d.ts +12 -0
- package/dist/commands/dump-tokens.js +69 -0
- package/dist/commands/env.d.ts +13 -0
- package/dist/commands/env.js +88 -0
- package/dist/commands/init.d.ts +9 -5
- package/dist/commands/init.js +241 -148
- package/dist/commands/list-tokens.d.ts +3 -3
- package/dist/commands/list-tokens.js +24 -9
- package/dist/commands/login.d.ts +8 -1
- package/dist/commands/login.js +34 -16
- package/dist/commands/logout.d.ts +5 -4
- package/dist/commands/logout.js +77 -15
- package/dist/commands/upgrade.d.ts +5 -0
- package/dist/commands/upgrade.js +331 -0
- package/dist/config/oauth.d.ts +17 -11
- package/dist/config/oauth.js +38 -37
- package/dist/constants.d.ts +63 -18
- package/dist/constants.js +158 -18
- package/dist/db-content-api/generated/content-api-types.d.ts +3978 -0
- package/dist/db-content-api/generated/content-api-types.js +7 -0
- package/dist/db-content-api/index.d.ts +37 -0
- package/dist/db-content-api/index.js +923 -0
- package/dist/db-content-api/temp-utilities/slug.d.ts +2 -0
- package/dist/db-content-api/temp-utilities/slug.js +3 -0
- package/dist/db-content-api/temp-utilities/sorting.d.ts +3 -0
- package/dist/db-content-api/temp-utilities/sorting.js +39 -0
- package/dist/db-content-api/temp-utilities/types.d.ts +22 -0
- package/dist/db-content-api/temp-utilities/types.js +15 -0
- package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts +39 -0
- package/dist/db-content-api/temp-utilities/unwrapDocument.js +64 -0
- package/dist/db-content-api/utilities/auth.d.ts +30 -0
- package/dist/db-content-api/utilities/auth.js +84 -0
- package/dist/db-content-api/utilities/data/applyDefaults.d.ts +7 -0
- package/dist/db-content-api/utilities/data/applyDefaults.js +75 -0
- package/dist/db-content-api/utilities/data/castFieldValue.d.ts +11 -0
- package/dist/db-content-api/utilities/data/castFieldValue.js +68 -0
- package/dist/db-content-api/utilities/data/index.d.ts +49 -0
- package/dist/db-content-api/utilities/data/index.js +301 -0
- package/dist/db-content-api/utilities/data/removeVirtualFields.d.ts +12 -0
- package/dist/db-content-api/utilities/data/removeVirtualFields.js +54 -0
- package/dist/db-content-api/utilities/data/stripFields.d.ts +48 -0
- package/dist/db-content-api/utilities/data/stripFields.js +195 -0
- package/dist/db-content-api/utilities/data/transformPublishedLocale.d.ts +23 -0
- package/dist/db-content-api/utilities/data/transformPublishedLocale.js +42 -0
- package/dist/db-content-api/utilities/data/validateRelationships.d.ts +7 -0
- package/dist/db-content-api/utilities/data/validateRelationships.js +102 -0
- package/dist/db-content-api/utilities/joins.d.ts +53 -0
- package/dist/db-content-api/utilities/joins.js +139 -0
- package/dist/db-content-api/utilities/locale/index.d.ts +10 -0
- package/dist/db-content-api/utilities/locale/index.js +21 -0
- package/dist/db-content-api/utilities/meta/buildLocalizedPaths.d.ts +11 -0
- package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js +74 -0
- package/dist/db-content-api/utilities/meta/buildMeta.d.ts +42 -0
- package/dist/db-content-api/utilities/meta/buildMeta.js +41 -0
- package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts +17 -0
- package/dist/db-content-api/utilities/meta/buildPathTypes.js +244 -0
- package/dist/db-content-api/utilities/meta/buildUniquePaths.d.ts +13 -0
- package/dist/db-content-api/utilities/meta/buildUniquePaths.js +62 -0
- package/dist/db-content-api/utilities/meta/normalizeLocaleInWhere.d.ts +10 -0
- package/dist/db-content-api/utilities/meta/normalizeLocaleInWhere.js +102 -0
- package/dist/db-content-api/utilities/where.d.ts +20 -0
- package/dist/db-content-api/utilities/where.js +108 -0
- package/dist/deploy/schedule-extract-plugin.d.ts +11 -0
- package/dist/deploy/schedule-extract-plugin.js +34 -0
- package/dist/endpoints/health.d.ts +3 -0
- package/dist/endpoints/health.js +11 -0
- package/dist/endpoints/schema.d.ts +3 -0
- package/dist/endpoints/schema.js +29 -0
- package/dist/exports/client.d.ts +3 -0
- package/dist/exports/client.js +3 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -1
- package/dist/lib/download-skill.d.ts +13 -0
- package/dist/lib/download-skill.js +79 -0
- package/dist/oauth/components/FigmaAvatar/index.d.ts +4 -0
- package/dist/oauth/components/FigmaAvatar/index.js +27 -0
- package/dist/oauth/components/FigmaAvatar/index.scss +12 -0
- package/dist/oauth/components/FigmaAvatarCell/index.d.ts +5 -0
- package/dist/oauth/components/FigmaAvatarCell/index.js +25 -0
- package/dist/oauth/components/FigmaAvatarCell/index.scss +5 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.d.ts +9 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.js +37 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.scss +28 -0
- package/dist/oauth/components/LoginButton/iframeAutoLogin.d.ts +82 -0
- package/dist/oauth/components/LoginButton/iframeAutoLogin.js +170 -0
- package/dist/oauth/components/LoginButton/index.js +144 -11
- package/dist/oauth/components/LoginButton/index.scss +75 -3
- package/dist/oauth/components/LogoutButton/index.js +19 -6
- package/dist/oauth/defaults.d.ts +3 -1
- package/dist/oauth/defaults.js +68 -10
- package/dist/oauth/endpoints/getLoginEndpoint.js +72 -77
- package/dist/oauth/endpoints/getLogoutEndpoint.js +7 -4
- package/dist/oauth/endpoints/getMetaEndpoint.js +18 -3
- package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js +11 -2
- package/dist/oauth/index.js +27 -5
- package/dist/oauth/strategy/index.d.ts +0 -2
- package/dist/oauth/strategy/index.js +40 -17
- package/dist/oauth/types.d.ts +23 -6
- package/dist/oauth/utilities/establishSession.d.ts +23 -0
- package/dist/oauth/utilities/establishSession.js +82 -0
- package/dist/oauth/utilities/exchangeCodeForAccessToken.d.ts +24 -0
- package/dist/oauth/utilities/exchangeCodeForAccessToken.js +28 -0
- package/dist/oauth/utilities/figmaHostnames.d.ts +3 -0
- package/dist/oauth/utilities/figmaHostnames.js +26 -0
- package/dist/oauth/utilities/getAuthorizeURL.d.ts +65 -1
- package/dist/oauth/utilities/getAuthorizeURL.js +57 -2
- package/dist/oauth/utilities/isAbsoluteURL.d.ts +2 -0
- package/dist/oauth/utilities/isAbsoluteURL.js +3 -0
- package/dist/oauth/utilities/isDuplicateKeyError.d.ts +7 -0
- package/dist/oauth/utilities/isDuplicateKeyError.js +14 -0
- package/dist/oauth/utilities/refreshTokens.js +6 -3
- package/dist/plugin/auth-preflight.d.ts +8 -0
- package/dist/plugin/auth-preflight.js +20 -0
- package/dist/plugin/bootstrap-preflight.d.ts +23 -0
- package/dist/plugin/bootstrap-preflight.js +45 -0
- package/dist/plugin/build-config.d.ts +27 -15
- package/dist/plugin/build-config.js +327 -17
- package/dist/plugin/dev-cookie-names.d.ts +14 -0
- package/dist/plugin/dev-cookie-names.js +19 -0
- package/dist/storage-content-api/api-types.d.ts +168 -0
- package/dist/storage-content-api/api-types.js +6 -0
- package/dist/storage-content-api/client-uploads/ClientUploadHandler.d.ts +9 -0
- package/dist/storage-content-api/client-uploads/ClientUploadHandler.js +43 -0
- package/dist/storage-content-api/client-uploads/generateSignedURL.d.ts +13 -0
- package/dist/storage-content-api/client-uploads/generateSignedURL.js +39 -0
- package/dist/storage-content-api/client.d.ts +6 -0
- package/dist/storage-content-api/client.js +39 -0
- package/dist/storage-content-api/generateURL.d.ts +7 -0
- package/dist/storage-content-api/generateURL.js +8 -0
- package/dist/storage-content-api/handleDelete.d.ts +8 -0
- package/dist/storage-content-api/handleDelete.js +17 -0
- package/dist/storage-content-api/handleUpload.d.ts +11 -0
- package/dist/storage-content-api/handleUpload.js +144 -0
- package/dist/storage-content-api/index.d.ts +5 -0
- package/dist/storage-content-api/index.js +31 -0
- package/dist/storage-content-api/staticHandler.d.ts +10 -0
- package/dist/storage-content-api/staticHandler.js +63 -0
- package/dist/storage-content-api/types.d.ts +10 -0
- package/dist/storage-content-api/types.js +3 -0
- package/dist/storage-content-api/utilities/getSafeFilename.d.ts +12 -0
- package/dist/storage-content-api/utilities/getSafeFilename.js +61 -0
- package/dist/storage-content-api/utilities/index.d.ts +3 -0
- package/dist/storage-content-api/utilities/index.js +4 -0
- package/dist/storage-content-api/utilities/parseClientUploadContext.d.ts +19 -0
- package/dist/storage-content-api/utilities/parseClientUploadContext.js +30 -0
- package/dist/templates/.env.example +5 -0
- package/dist/templates/README.md +19 -0
- package/dist/types/config.d.ts +2 -1
- package/dist/types/config.js +0 -2
- package/dist/types.d.ts +10 -1
- package/dist/utils/adapters/nextjs.d.ts +9 -0
- package/dist/utils/adapters/nextjs.js +64 -0
- package/dist/utils/adapters/nitro.d.ts +9 -0
- package/dist/utils/adapters/nitro.js +169 -0
- package/dist/utils/adapters/vite.d.ts +10 -0
- package/dist/utils/adapters/vite.js +33 -0
- package/dist/utils/asset-collection.d.ts +27 -6
- package/dist/utils/asset-collection.js +59 -30
- package/dist/utils/build-detection.d.ts +5 -11
- package/dist/utils/build-detection.js +74 -11
- package/dist/utils/build-lambda-zip.d.ts +16 -0
- package/dist/utils/build-lambda-zip.js +78 -0
- package/dist/utils/cache-bootstrap.d.ts +8 -0
- package/dist/utils/cache-bootstrap.js +18 -0
- package/dist/utils/config.js +1 -1
- package/dist/utils/deploy-adapter.d.ts +40 -0
- package/dist/utils/deploy-adapter.js +58 -0
- package/dist/utils/download-template.d.ts +9 -1
- package/dist/utils/download-template.js +24 -18
- package/dist/utils/env-management.d.ts +24 -7
- package/dist/utils/env-management.js +119 -64
- package/dist/utils/format-env-suffix.d.ts +12 -0
- package/dist/utils/format-env-suffix.js +13 -0
- package/dist/utils/formatter.js +23 -11
- package/dist/utils/fs-utils.d.ts +6 -0
- package/dist/utils/fs-utils.js +27 -0
- package/dist/utils/handle-upgrade.d.ts +9 -0
- package/dist/utils/handle-upgrade.js +41 -0
- package/dist/utils/lambda-config.d.ts +3 -1
- package/dist/utils/lambda-config.js +75 -78
- package/dist/utils/messages.d.ts +1 -2
- package/dist/utils/messages.js +39 -11
- package/dist/utils/package-manager.d.ts +24 -0
- package/dist/utils/package-manager.js +53 -0
- package/dist/utils/parse-template-spec.d.ts +12 -0
- package/dist/utils/parse-template-spec.js +62 -0
- package/dist/utils/payload-config-ast.d.ts +27 -6
- package/dist/utils/payload-config-ast.js +106 -58
- package/dist/utils/payload-config-finder.d.ts +2 -2
- package/dist/utils/payload-config-finder.js +48 -9
- package/dist/utils/payload-config-modifier.d.ts +1 -1
- package/dist/utils/payload-config-modifier.js +114 -66
- package/dist/utils/payload-package-check.d.ts +33 -2
- package/dist/utils/payload-package-check.js +129 -28
- package/dist/utils/project.d.ts +7 -2
- package/dist/utils/project.js +60 -32
- package/dist/utils/resolve-environment.d.ts +14 -0
- package/dist/utils/resolve-environment.js +31 -0
- package/dist/utils/s3-upload.d.ts +7 -2
- package/dist/utils/s3-upload.js +39 -6
- package/dist/utils/token-display.d.ts +5 -1
- package/dist/utils/token-display.js +49 -22
- package/dist/utils/typescript-validator.js +4 -6
- package/dist/utils/version-check.d.ts +3 -0
- package/dist/utils/version-check.js +38 -0
- package/package.json +44 -15
- package/dist/api/control-plane.d.ts.map +0 -1
- package/dist/api/control-plane.js.map +0 -1
- package/dist/api/figma-api.d.ts.map +0 -1
- package/dist/api/figma-api.js.map +0 -1
- package/dist/auth/browser.d.ts.map +0 -1
- package/dist/auth/browser.js.map +0 -1
- package/dist/auth/callback-server.d.ts.map +0 -1
- package/dist/auth/callback-server.js.map +0 -1
- package/dist/auth/crypto-utils.d.ts.map +0 -1
- package/dist/auth/crypto-utils.js.map +0 -1
- package/dist/auth/jwt-validator.d.ts.map +0 -1
- package/dist/auth/jwt-validator.js.map +0 -1
- package/dist/auth/oauth-flow.d.ts.map +0 -1
- package/dist/auth/oauth-flow.js.map +0 -1
- package/dist/auth/pkce.d.ts.map +0 -1
- package/dist/auth/pkce.js.map +0 -1
- package/dist/auth/project-token.d.ts.map +0 -1
- package/dist/auth/project-token.js.map +0 -1
- package/dist/auth/refresh.d.ts.map +0 -1
- package/dist/auth/refresh.js.map +0 -1
- package/dist/auth/token-store.d.ts.map +0 -1
- package/dist/auth/token-store.js.map +0 -1
- package/dist/auth/types.d.ts.map +0 -1
- package/dist/auth/types.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/deploy.d.ts.map +0 -1
- package/dist/commands/deploy.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/list-tokens.d.ts.map +0 -1
- package/dist/commands/list-tokens.js.map +0 -1
- package/dist/commands/login.d.ts.map +0 -1
- package/dist/commands/login.js.map +0 -1
- package/dist/commands/logout.d.ts.map +0 -1
- package/dist/commands/logout.js.map +0 -1
- package/dist/config/oauth.d.ts.map +0 -1
- package/dist/config/oauth.js.map +0 -1
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/exports/client.d.ts.map +0 -1
- package/dist/exports/client.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/oauth/components/LoginButton/index.d.ts.map +0 -1
- package/dist/oauth/components/LoginButton/index.js.map +0 -1
- package/dist/oauth/components/LogoutButton/index.d.ts.map +0 -1
- package/dist/oauth/components/LogoutButton/index.js.map +0 -1
- package/dist/oauth/defaults.d.ts.map +0 -1
- package/dist/oauth/defaults.js.map +0 -1
- package/dist/oauth/endpoints/getLoginEndpoint.d.ts.map +0 -1
- package/dist/oauth/endpoints/getLoginEndpoint.js.map +0 -1
- package/dist/oauth/endpoints/getLogoutEndpoint.d.ts.map +0 -1
- package/dist/oauth/endpoints/getLogoutEndpoint.js.map +0 -1
- package/dist/oauth/endpoints/getMetaEndpoint.d.ts.map +0 -1
- package/dist/oauth/endpoints/getMetaEndpoint.js.map +0 -1
- package/dist/oauth/endpoints/getRedirectToLoginEndpoint.d.ts.map +0 -1
- package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js.map +0 -1
- package/dist/oauth/exports/client.d.ts.map +0 -1
- package/dist/oauth/exports/client.js.map +0 -1
- package/dist/oauth/hooks/afterLogout.d.ts.map +0 -1
- package/dist/oauth/hooks/afterLogout.js.map +0 -1
- package/dist/oauth/hooks/me.d.ts.map +0 -1
- package/dist/oauth/hooks/me.js.map +0 -1
- package/dist/oauth/hooks/refresh.d.ts.map +0 -1
- package/dist/oauth/hooks/refresh.js.map +0 -1
- package/dist/oauth/index.d.ts.map +0 -1
- package/dist/oauth/index.js.map +0 -1
- package/dist/oauth/strategy/index.d.ts.map +0 -1
- package/dist/oauth/strategy/index.js.map +0 -1
- package/dist/oauth/types.d.ts.map +0 -1
- package/dist/oauth/types.js.map +0 -1
- package/dist/oauth/utilities/clearCookie.d.ts.map +0 -1
- package/dist/oauth/utilities/clearCookie.js.map +0 -1
- package/dist/oauth/utilities/createCookieOptions.d.ts.map +0 -1
- package/dist/oauth/utilities/createCookieOptions.js.map +0 -1
- package/dist/oauth/utilities/createDebugLogger.d.ts.map +0 -1
- package/dist/oauth/utilities/createDebugLogger.js.map +0 -1
- package/dist/oauth/utilities/extractOrigin.d.ts.map +0 -1
- package/dist/oauth/utilities/extractOrigin.js.map +0 -1
- package/dist/oauth/utilities/getAdminCollectionSlug.d.ts.map +0 -1
- package/dist/oauth/utilities/getAdminCollectionSlug.js.map +0 -1
- package/dist/oauth/utilities/getAdminPath.d.ts +0 -8
- package/dist/oauth/utilities/getAdminPath.d.ts.map +0 -1
- package/dist/oauth/utilities/getAdminPath.js +0 -9
- package/dist/oauth/utilities/getAdminPath.js.map +0 -1
- package/dist/oauth/utilities/getAuthorizeURL.d.ts.map +0 -1
- package/dist/oauth/utilities/getAuthorizeURL.js.map +0 -1
- package/dist/oauth/utilities/getCookieExpiration.d.ts.map +0 -1
- package/dist/oauth/utilities/getCookieExpiration.js.map +0 -1
- package/dist/oauth/utilities/getSecondsFromTokenExp.d.ts.map +0 -1
- package/dist/oauth/utilities/getSecondsFromTokenExp.js.map +0 -1
- package/dist/oauth/utilities/getTokenExp.d.ts.map +0 -1
- package/dist/oauth/utilities/getTokenExp.js.map +0 -1
- package/dist/oauth/utilities/getUsernameField.d.ts.map +0 -1
- package/dist/oauth/utilities/getUsernameField.js.map +0 -1
- package/dist/oauth/utilities/hasUserTokenPropsChanged.d.ts.map +0 -1
- package/dist/oauth/utilities/hasUserTokenPropsChanged.js.map +0 -1
- package/dist/oauth/utilities/mergeHeaders.d.ts.map +0 -1
- package/dist/oauth/utilities/mergeHeaders.js.map +0 -1
- package/dist/oauth/utilities/refreshTokens.d.ts.map +0 -1
- package/dist/oauth/utilities/refreshTokens.js.map +0 -1
- package/dist/plugin/adapter.d.ts.map +0 -1
- package/dist/plugin/adapter.js.map +0 -1
- package/dist/plugin/build-config.d.ts.map +0 -1
- package/dist/plugin/build-config.js.map +0 -1
- package/dist/types/config.d.ts.map +0 -1
- package/dist/types/config.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils/asset-collection.d.ts.map +0 -1
- package/dist/utils/asset-collection.js.map +0 -1
- package/dist/utils/build-detection.d.ts.map +0 -1
- package/dist/utils/build-detection.js.map +0 -1
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js.map +0 -1
- package/dist/utils/download-template.d.ts.map +0 -1
- package/dist/utils/download-template.js.map +0 -1
- package/dist/utils/env-management.d.ts.map +0 -1
- package/dist/utils/env-management.js.map +0 -1
- package/dist/utils/format.d.ts.map +0 -1
- package/dist/utils/format.js.map +0 -1
- package/dist/utils/formatter.d.ts.map +0 -1
- package/dist/utils/formatter.js.map +0 -1
- package/dist/utils/git.d.ts.map +0 -1
- package/dist/utils/git.js.map +0 -1
- package/dist/utils/is-debug.d.ts.map +0 -1
- package/dist/utils/is-debug.js.map +0 -1
- package/dist/utils/lambda-config.d.ts.map +0 -1
- package/dist/utils/lambda-config.js.map +0 -1
- package/dist/utils/log.d.ts.map +0 -1
- package/dist/utils/log.js.map +0 -1
- package/dist/utils/messages.d.ts.map +0 -1
- package/dist/utils/messages.js.map +0 -1
- package/dist/utils/package-manager.d.ts.map +0 -1
- package/dist/utils/package-manager.js.map +0 -1
- package/dist/utils/payload-config-ast.d.ts.map +0 -1
- package/dist/utils/payload-config-ast.js.map +0 -1
- package/dist/utils/payload-config-finder.d.ts.map +0 -1
- package/dist/utils/payload-config-finder.js.map +0 -1
- package/dist/utils/payload-config-modifier.d.ts.map +0 -1
- package/dist/utils/payload-config-modifier.js.map +0 -1
- package/dist/utils/payload-package-check.d.ts.map +0 -1
- package/dist/utils/payload-package-check.js.map +0 -1
- package/dist/utils/project.d.ts.map +0 -1
- package/dist/utils/project.js.map +0 -1
- package/dist/utils/s3-upload.d.ts.map +0 -1
- package/dist/utils/s3-upload.js.map +0 -1
- package/dist/utils/token-display.d.ts.map +0 -1
- package/dist/utils/token-display.js.map +0 -1
- package/dist/utils/typescript-validator.d.ts.map +0 -1
- package/dist/utils/typescript-validator.js.map +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AuthCredential } from './credentials.js';
|
|
1
2
|
import type { TokenStore } from './token-store.js';
|
|
2
3
|
import type { FigmaTokens } from './types.js';
|
|
3
4
|
/**
|
|
@@ -13,7 +14,9 @@ export declare class OAuthFlowError extends Error {
|
|
|
13
14
|
export interface OAuthFlowOptions {
|
|
14
15
|
/** OAuth2 client ID (defaults to config) */
|
|
15
16
|
clientId?: string;
|
|
16
|
-
/** Callback server
|
|
17
|
+
/** Callback server fallback ports to try after port */
|
|
18
|
+
fallbackPorts?: number[];
|
|
19
|
+
/** First callback server port to try */
|
|
17
20
|
port?: number;
|
|
18
21
|
/** Redirect URI (defaults to config) */
|
|
19
22
|
redirectUri?: string;
|
|
@@ -55,8 +58,21 @@ export declare function executeOAuthFlow(tokenStore: TokenStore, options?: OAuth
|
|
|
55
58
|
* refreshes using the refresh token. If no tokens exist, returns null.
|
|
56
59
|
*
|
|
57
60
|
* @param tokenStore - Token store to use
|
|
58
|
-
* @returns Promise resolving to access token or null if no valid tokens
|
|
61
|
+
* @returns Promise resolving to AuthCredential (wrapped access token) or null if no valid tokens
|
|
59
62
|
* @throws OAuthFlowError if refresh fails
|
|
60
63
|
*/
|
|
61
|
-
export declare function
|
|
64
|
+
export declare function getValidOAuthAccessToken(tokenStore: TokenStore): Promise<AuthCredential | null>;
|
|
65
|
+
/**
|
|
66
|
+
* Get a valid auth credential, checking process.env for plan access token
|
|
67
|
+
* first before checking tokenStore for OAuth tokens.
|
|
68
|
+
* *
|
|
69
|
+
* @param tokenStore - Token store to use for OAuth tokens
|
|
70
|
+
* @returns Promise resolving to AuthCredential or null
|
|
71
|
+
*/
|
|
72
|
+
export declare function getValidCredential(tokenStore: TokenStore): Promise<AuthCredential | null>;
|
|
73
|
+
/**
|
|
74
|
+
* Like getValidCredential but returns null instead of throwing on refresh failure.
|
|
75
|
+
* Use in commands that want to fall through to a login prompt on failure.
|
|
76
|
+
*/
|
|
77
|
+
export declare function tryGetCredential(tokenStore: TokenStore): Promise<AuthCredential | null>;
|
|
62
78
|
//# sourceMappingURL=oauth-flow.d.ts.map
|
package/dist/auth/oauth-flow.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as p from '@clack/prompts';
|
|
2
2
|
import crypto from 'crypto';
|
|
3
|
-
import {
|
|
3
|
+
import { getOAuthConfig } from '../config/oauth.js';
|
|
4
4
|
import * as log from '../utils/log.js';
|
|
5
5
|
import { buildAuthorizationUrl, openBrowser } from './browser.js';
|
|
6
6
|
import { CallbackServer } from './callback-server.js';
|
|
7
7
|
import { generatePKCEPair } from './pkce.js';
|
|
8
|
-
import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
8
|
+
import { exchangeCodeForTokens, refreshAccessToken, TokenRefreshError } from './refresh.js';
|
|
9
9
|
/**
|
|
10
10
|
* Error during OAuth flow
|
|
11
11
|
*/ export class OAuthFlowError extends Error {
|
|
@@ -32,16 +32,17 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
|
32
32
|
* @throws OAuthFlowError if any step fails
|
|
33
33
|
*/ export async function executeOAuthFlow(tokenStore, options = {}) {
|
|
34
34
|
// Check if OAuth flow should be mocked
|
|
35
|
-
// Default to
|
|
36
|
-
const shouldMock = process.env.FIGMA_MOCK_OAUTH
|
|
35
|
+
// Default to false for OAuth
|
|
36
|
+
const shouldMock = process.env.FIGMA_MOCK_OAUTH === 'true';
|
|
37
|
+
const oauthConfig = getOAuthConfig();
|
|
37
38
|
if (shouldMock) {
|
|
38
39
|
// MOCK IMPLEMENTATION: Return mock tokens for testing
|
|
39
|
-
log.debug('Using mock OAuth flow (FIGMA_MOCK_OAUTH
|
|
40
|
+
log.debug('Using mock OAuth flow (FIGMA_MOCK_OAUTH = true)');
|
|
40
41
|
const mockTokens = {
|
|
41
42
|
accessToken: 'figt_mock_access_token_' + crypto.randomBytes(16).toString('hex'),
|
|
42
43
|
expiresAt: Date.now() + 2 * 60 * 60 * 1000,
|
|
43
44
|
refreshToken: 'figt_mock_refresh_token_' + crypto.randomBytes(16).toString('hex'),
|
|
44
|
-
scopes: options.scopes ||
|
|
45
|
+
scopes: options.scopes || oauthConfig.scopes,
|
|
45
46
|
tokenType: 'Bearer'
|
|
46
47
|
};
|
|
47
48
|
// Store mock tokens
|
|
@@ -52,28 +53,30 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
|
52
53
|
};
|
|
53
54
|
}
|
|
54
55
|
// REAL OAUTH IMPLEMENTATION
|
|
55
|
-
const { clientId =
|
|
56
|
+
const { clientId = oauthConfig.clientId, fallbackPorts, port, redirectUri = oauthConfig.redirectUri, scopes = oauthConfig.scopes, timeoutMs = 120000 } = options;
|
|
56
57
|
// Generate PKCE pair for enhanced security
|
|
57
58
|
const { codeChallenge, codeChallengeMethod, codeVerifier } = generatePKCEPair();
|
|
58
59
|
// Generate random state for CSRF protection
|
|
59
60
|
const state = crypto.randomBytes(32).toString('base64url');
|
|
60
61
|
// Create callback server
|
|
61
62
|
const callbackServer = new CallbackServer({
|
|
63
|
+
fallbackPorts,
|
|
62
64
|
port,
|
|
63
65
|
timeoutMs
|
|
64
66
|
});
|
|
65
67
|
try {
|
|
66
68
|
// Start waiting for callback (this starts the server and captures actual port)
|
|
67
69
|
const callbackPromise = callbackServer.waitForCallback(state);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
callbackPromise.catch(()=>{
|
|
71
|
+
// The callback promise is awaited below; avoid an unhandled rejection if startup fails early.
|
|
72
|
+
});
|
|
70
73
|
// Get the actual port (may differ from preferred if that was in use)
|
|
71
|
-
const actualPort = callbackServer.
|
|
74
|
+
const actualPort = await callbackServer.waitUntilReady();
|
|
72
75
|
// Build redirect URI with actual port
|
|
73
|
-
const actualRedirectUri = redirectUri
|
|
76
|
+
const actualRedirectUri = replaceRedirectUriPort(redirectUri, actualPort);
|
|
74
77
|
// Build authorization URL
|
|
75
78
|
const authUrl = buildAuthorizationUrl({
|
|
76
|
-
authorizationUrl:
|
|
79
|
+
authorizationUrl: oauthConfig.authorizationUrl,
|
|
77
80
|
clientId,
|
|
78
81
|
codeChallenge,
|
|
79
82
|
codeChallengeMethod,
|
|
@@ -84,7 +87,7 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
|
84
87
|
// Prompt user to open browser
|
|
85
88
|
const shouldOpenBrowser = await p.confirm({
|
|
86
89
|
initialValue: true,
|
|
87
|
-
message: '
|
|
90
|
+
message: 'Authenticate with Figma in your browser?'
|
|
88
91
|
});
|
|
89
92
|
if (p.isCancel(shouldOpenBrowser)) {
|
|
90
93
|
throw new OAuthFlowError('Authentication cancelled by user');
|
|
@@ -142,28 +145,80 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
|
142
145
|
* refreshes using the refresh token. If no tokens exist, returns null.
|
|
143
146
|
*
|
|
144
147
|
* @param tokenStore - Token store to use
|
|
145
|
-
* @returns Promise resolving to access token or null if no valid tokens
|
|
148
|
+
* @returns Promise resolving to AuthCredential (wrapped access token) or null if no valid tokens
|
|
146
149
|
* @throws OAuthFlowError if refresh fails
|
|
147
|
-
*/ export async function
|
|
150
|
+
*/ export async function getValidOAuthAccessToken(tokenStore) {
|
|
148
151
|
// Check if we have valid tokens
|
|
149
|
-
if (tokenStore.
|
|
150
|
-
|
|
152
|
+
if (tokenStore.hasValidOauthToken()) {
|
|
153
|
+
const token = tokenStore.getCurrentOauthToken();
|
|
154
|
+
return token ? {
|
|
155
|
+
type: 'oauth',
|
|
156
|
+
token
|
|
157
|
+
} : null;
|
|
151
158
|
}
|
|
152
159
|
// Check if we have a refresh token
|
|
153
|
-
const refreshToken = tokenStore.
|
|
160
|
+
const refreshToken = tokenStore.getCurrentRefreshToken();
|
|
154
161
|
if (!refreshToken) {
|
|
155
162
|
return null;
|
|
156
163
|
}
|
|
157
|
-
// Try to refresh
|
|
164
|
+
// Try to refresh (with one retry for transient auth errors)
|
|
158
165
|
try {
|
|
159
166
|
const tokens = await refreshAccessToken(refreshToken);
|
|
160
167
|
tokenStore.setTokens(tokens);
|
|
161
|
-
return
|
|
168
|
+
return {
|
|
169
|
+
type: 'oauth',
|
|
170
|
+
token: tokens.accessToken
|
|
171
|
+
};
|
|
162
172
|
} catch (error) {
|
|
163
|
-
|
|
164
|
-
|
|
173
|
+
const isAuthFailure = error instanceof TokenRefreshError && (error.statusCode === 401 || error.statusCode === 403 || error.statusCode === 400 && error.errorCode === 'invalid_grant');
|
|
174
|
+
if (isAuthFailure) {
|
|
175
|
+
// Retry once — a transient 401 (e.g. misconfigured proxy) shouldn't wipe tokens
|
|
176
|
+
try {
|
|
177
|
+
const tokens = await refreshAccessToken(refreshToken);
|
|
178
|
+
tokenStore.setTokens(tokens);
|
|
179
|
+
return {
|
|
180
|
+
type: 'oauth',
|
|
181
|
+
token: tokens.accessToken
|
|
182
|
+
};
|
|
183
|
+
} catch {
|
|
184
|
+
// Retry also failed — token is genuinely revoked
|
|
185
|
+
tokenStore.clearTokens();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
165
188
|
throw new OAuthFlowError('Failed to refresh access token', error instanceof Error ? error : undefined);
|
|
166
189
|
}
|
|
167
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Get a valid auth credential, checking process.env for plan access token
|
|
193
|
+
* first before checking tokenStore for OAuth tokens.
|
|
194
|
+
* *
|
|
195
|
+
* @param tokenStore - Token store to use for OAuth tokens
|
|
196
|
+
* @returns Promise resolving to AuthCredential or null
|
|
197
|
+
*/ export async function getValidCredential(tokenStore) {
|
|
198
|
+
const envFigmaAccessToken = process.env.FIGMA_ACCESS_TOKEN;
|
|
199
|
+
if (envFigmaAccessToken) {
|
|
200
|
+
log.debug('Using FIGMA_ACCESS_TOKEN env var override; skipping stored OAuth tokens');
|
|
201
|
+
return {
|
|
202
|
+
type: 'plan_access_token',
|
|
203
|
+
token: envFigmaAccessToken
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
return getValidOAuthAccessToken(tokenStore);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Like getValidCredential but returns null instead of throwing on refresh failure.
|
|
210
|
+
* Use in commands that want to fall through to a login prompt on failure.
|
|
211
|
+
*/ export async function tryGetCredential(tokenStore) {
|
|
212
|
+
try {
|
|
213
|
+
return await getValidCredential(tokenStore);
|
|
214
|
+
} catch {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function replaceRedirectUriPort(redirectUri, port) {
|
|
219
|
+
const url = new URL(redirectUri);
|
|
220
|
+
url.port = String(port);
|
|
221
|
+
return url.toString();
|
|
222
|
+
}
|
|
168
223
|
|
|
169
224
|
//# sourceMappingURL=oauth-flow.js.map
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* and have a shorter lifespan (15-30 minutes) than OAuth tokens.
|
|
7
7
|
*/
|
|
8
8
|
import type { TokenStore } from './token-store.js';
|
|
9
|
+
import type { ProjectStoreScope } from './types.js';
|
|
9
10
|
/**
|
|
10
11
|
* Error during project token operations
|
|
11
12
|
*/
|
|
@@ -13,35 +14,50 @@ export declare class ProjectTokenError extends Error {
|
|
|
13
14
|
cause?: Error | undefined;
|
|
14
15
|
constructor(message: string, cause?: Error | undefined);
|
|
15
16
|
}
|
|
17
|
+
/** Test-only: clears the in-memory token cache and any in-flight refresh promises. */
|
|
18
|
+
export declare function __resetProjectTokenCacheForTests(): void;
|
|
16
19
|
/**
|
|
17
|
-
* Get a valid project token for a tenant, refreshing if necessary
|
|
20
|
+
* Get a valid project token for a tenant, refreshing if necessary.
|
|
18
21
|
*
|
|
19
|
-
*
|
|
20
|
-
* 1.
|
|
21
|
-
* 2.
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
22
|
+
* Lookup order:
|
|
23
|
+
* 1. Module-level in-memory cache (no I/O on hits).
|
|
24
|
+
* 2. In-flight refresh map — concurrent callers with no cached entry share a single
|
|
25
|
+
* refresh promise, so the project-token endpoint is only hit once per cache key.
|
|
26
|
+
* 3. Persisted (`conf`-backed) token store — picks up tokens minted by sibling processes.
|
|
27
|
+
* 4. Figma API — fetch + JWT validation, then write to both the persisted store and
|
|
28
|
+
* the in-memory cache.
|
|
25
29
|
*
|
|
26
30
|
* The project token is used by local Payload instances to authenticate
|
|
27
31
|
* requests to the Content API without requiring a round-trip to Sinatra.
|
|
28
32
|
*
|
|
29
|
-
* @param tokenStore - Token store for persisting tokens
|
|
30
|
-
* @param tenantId -
|
|
33
|
+
* @param params.tokenStore - Token store for persisting tokens
|
|
34
|
+
* @param params.tenantId - Optional tenant/CMS ID; resolved from stored bootstrap data when omitted
|
|
35
|
+
* @param params.projectInfo - Optional project scope (defaults to env vars)
|
|
31
36
|
* @returns Promise resolving to JWT token string or null if failed
|
|
32
37
|
* @throws {ProjectTokenError} If token generation fails
|
|
33
38
|
*/
|
|
34
|
-
export declare function getValidProjectToken(
|
|
39
|
+
export declare function getValidProjectToken({ projectInfo, tenantId, tokenStore, }: {
|
|
40
|
+
projectInfo?: ProjectStoreScope;
|
|
41
|
+
tenantId?: string;
|
|
42
|
+
tokenStore: TokenStore;
|
|
43
|
+
}): Promise<null | string>;
|
|
35
44
|
/**
|
|
36
|
-
*
|
|
45
|
+
* Force-refresh a project token, bypassing all cache layers.
|
|
37
46
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
47
|
+
* Invalidates the in-memory cache entry, the in-flight refresh promise (so a
|
|
48
|
+
* concurrently-running refresh that may already be returning a soon-to-be-stale
|
|
49
|
+
* token is dropped from the dedup map), and the persisted token store. Then
|
|
50
|
+
* delegates to {@link getValidProjectToken} to mint a fresh token.
|
|
40
51
|
*
|
|
41
|
-
* @param tokenStore - Token store for persisting tokens
|
|
42
|
-
* @param tenantId -
|
|
52
|
+
* @param params.tokenStore - Token store for persisting tokens
|
|
53
|
+
* @param params.tenantId - Optional tenant/CMS ID; resolved from stored bootstrap data when omitted
|
|
54
|
+
* @param params.projectInfo - Optional project scope (defaults to env vars)
|
|
43
55
|
* @returns Promise resolving to JWT token string or null if failed
|
|
44
56
|
* @throws {ProjectTokenError} If token refresh fails
|
|
45
57
|
*/
|
|
46
|
-
export declare function refreshProjectToken(
|
|
58
|
+
export declare function refreshProjectToken(params: {
|
|
59
|
+
projectInfo?: ProjectStoreScope;
|
|
60
|
+
tenantId?: string;
|
|
61
|
+
tokenStore: TokenStore;
|
|
62
|
+
}): Promise<null | string>;
|
|
47
63
|
//# sourceMappingURL=project-token.d.ts.map
|
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
* to the Content API. Project tokens are scoped to a specific tenant/CMS
|
|
6
6
|
* and have a shorter lifespan (15-30 minutes) than OAuth tokens.
|
|
7
7
|
*/ import { getProjectToken as fetchProjectToken } from '../api/figma-api.js';
|
|
8
|
-
import {
|
|
8
|
+
import { PROJECT_TOKEN_EXPIRY_BUFFER_SECONDS } from '../config/oauth.js';
|
|
9
|
+
import { getInfraEnvironment } from '../constants.js';
|
|
9
10
|
import * as log from '../utils/log.js';
|
|
10
11
|
import { JWTValidationError, validateProjectToken } from './jwt-validator.js';
|
|
11
|
-
import {
|
|
12
|
+
import { getValidCredential } from './oauth-flow.js';
|
|
12
13
|
/**
|
|
13
14
|
* Error during project token operations
|
|
14
15
|
*/ export class ProjectTokenError extends Error {
|
|
@@ -18,6 +19,21 @@ import { getValidAccessToken } from './oauth-flow.js';
|
|
|
18
19
|
this.name = 'ProjectTokenError';
|
|
19
20
|
}
|
|
20
21
|
}
|
|
22
|
+
const projectTokenCache = new Map();
|
|
23
|
+
const inFlightRefreshes = new Map();
|
|
24
|
+
function buildCacheKey(params) {
|
|
25
|
+
const projectId = params.projectInfo?.projectId ?? '';
|
|
26
|
+
const environmentName = params.projectInfo?.environmentName ?? '';
|
|
27
|
+
return `${params.tenantId}::${projectId}::${environmentName}`;
|
|
28
|
+
}
|
|
29
|
+
function isCachedTokenValid(entry) {
|
|
30
|
+
const bufferMs = PROJECT_TOKEN_EXPIRY_BUFFER_SECONDS * 1000;
|
|
31
|
+
return Date.now() < entry.expiresAt - bufferMs;
|
|
32
|
+
}
|
|
33
|
+
/** Test-only: clears the in-memory token cache and any in-flight refresh promises. */ export function __resetProjectTokenCacheForTests() {
|
|
34
|
+
projectTokenCache.clear();
|
|
35
|
+
inFlightRefreshes.clear();
|
|
36
|
+
}
|
|
21
37
|
/**
|
|
22
38
|
* Parse JWT claims from token without validation
|
|
23
39
|
* Used for mock tokens where signature validation is not needed
|
|
@@ -43,89 +59,179 @@ import { getValidAccessToken } from './oauth-flow.js';
|
|
|
43
59
|
}
|
|
44
60
|
}
|
|
45
61
|
/**
|
|
46
|
-
* Get a valid project token for a tenant, refreshing if necessary
|
|
62
|
+
* Get a valid project token for a tenant, refreshing if necessary.
|
|
47
63
|
*
|
|
48
|
-
*
|
|
49
|
-
* 1.
|
|
50
|
-
* 2.
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
64
|
+
* Lookup order:
|
|
65
|
+
* 1. Module-level in-memory cache (no I/O on hits).
|
|
66
|
+
* 2. In-flight refresh map — concurrent callers with no cached entry share a single
|
|
67
|
+
* refresh promise, so the project-token endpoint is only hit once per cache key.
|
|
68
|
+
* 3. Persisted (`conf`-backed) token store — picks up tokens minted by sibling processes.
|
|
69
|
+
* 4. Figma API — fetch + JWT validation, then write to both the persisted store and
|
|
70
|
+
* the in-memory cache.
|
|
54
71
|
*
|
|
55
72
|
* The project token is used by local Payload instances to authenticate
|
|
56
73
|
* requests to the Content API without requiring a round-trip to Sinatra.
|
|
57
74
|
*
|
|
58
|
-
* @param tokenStore - Token store for persisting tokens
|
|
59
|
-
* @param tenantId -
|
|
75
|
+
* @param params.tokenStore - Token store for persisting tokens
|
|
76
|
+
* @param params.tenantId - Optional tenant/CMS ID; resolved from stored bootstrap data when omitted
|
|
77
|
+
* @param params.projectInfo - Optional project scope (defaults to env vars)
|
|
60
78
|
* @returns Promise resolving to JWT token string or null if failed
|
|
61
79
|
* @throws {ProjectTokenError} If token generation fails
|
|
62
|
-
*/ export async function getValidProjectToken(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return projectToken?.token || null;
|
|
80
|
+
*/ export async function getValidProjectToken({ projectInfo, tenantId, tokenStore }) {
|
|
81
|
+
if (process.env.FIGMA_CONTENT_API_ACCESS_KEY) {
|
|
82
|
+
log.debug('FIGMA_CONTENT_API_ACCESS_KEY is set; skipping project token retrieval from API');
|
|
83
|
+
return null;
|
|
67
84
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
} catch (error) {
|
|
74
|
-
throw new ProjectTokenError('Failed to get valid access token for project token refresh', error instanceof Error ? error : undefined);
|
|
85
|
+
const resolvedTenantId = tenantId ?? tokenStore.getTenantId({
|
|
86
|
+
projectInfo
|
|
87
|
+
});
|
|
88
|
+
if (!resolvedTenantId) {
|
|
89
|
+
throw new ProjectTokenError('tenantId was not provided and could not be resolved from bootstrap data');
|
|
75
90
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
91
|
+
const cacheKey = buildCacheKey({
|
|
92
|
+
projectInfo,
|
|
93
|
+
tenantId: resolvedTenantId
|
|
94
|
+
});
|
|
95
|
+
const cached = projectTokenCache.get(cacheKey);
|
|
96
|
+
if (cached && isCachedTokenValid(cached)) {
|
|
97
|
+
return cached.token;
|
|
79
98
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
99
|
+
const inFlight = inFlightRefreshes.get(cacheKey);
|
|
100
|
+
if (inFlight) {
|
|
101
|
+
return inFlight;
|
|
102
|
+
}
|
|
103
|
+
// The IIFE references this holder so it can check whether it is still the
|
|
104
|
+
// active refresh before writing back to the caches. Without this guard a
|
|
105
|
+
// stale in-flight refresh could clobber a fresh token written by a later
|
|
106
|
+
// refresh (e.g. one triggered by `refreshProjectToken`).
|
|
107
|
+
const handle = {};
|
|
108
|
+
handle.promise = (async ()=>{
|
|
109
|
+
if (tokenStore.hasValidProjectToken({
|
|
110
|
+
projectInfo
|
|
111
|
+
})) {
|
|
112
|
+
const stored = tokenStore.getProjectToken({
|
|
113
|
+
projectInfo
|
|
114
|
+
});
|
|
115
|
+
if (stored?.token && inFlightRefreshes.get(cacheKey) === handle.promise) {
|
|
116
|
+
projectTokenCache.set(cacheKey, {
|
|
117
|
+
expiresAt: stored.expiresAt,
|
|
118
|
+
token: stored.token
|
|
119
|
+
});
|
|
120
|
+
return stored.token;
|
|
121
|
+
}
|
|
122
|
+
if (stored?.token) {
|
|
123
|
+
return stored.token;
|
|
124
|
+
}
|
|
125
|
+
// hasValidProjectToken said yes but getProjectToken returned no token —
|
|
126
|
+
// store was likely cleared by another process between calls. Fall through
|
|
127
|
+
// to fetch so the caller still gets a token.
|
|
128
|
+
log.warning(`Stored project token vanished between hasValidProjectToken and getProjectToken (cacheKey=${cacheKey}); re-fetching`);
|
|
129
|
+
}
|
|
130
|
+
let credential;
|
|
131
|
+
try {
|
|
132
|
+
credential = await getValidCredential(tokenStore);
|
|
133
|
+
} catch (error) {
|
|
134
|
+
throw new ProjectTokenError('Failed to get valid access token for project token refresh', error instanceof Error ? error : undefined);
|
|
135
|
+
}
|
|
136
|
+
if (!credential) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
let fetchedToken;
|
|
91
140
|
try {
|
|
92
|
-
|
|
93
|
-
} catch (
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
141
|
+
fetchedToken = await fetchProjectToken(credential, resolvedTenantId);
|
|
142
|
+
} catch (error) {
|
|
143
|
+
// Let API errors (e.g. FigmaApiError) propagate raw so callers can
|
|
144
|
+
// branch on status codes — but log context for debugging.
|
|
145
|
+
log.debug(`fetchProjectToken failed (cacheKey=${cacheKey}, tenantId=${resolvedTenantId}): ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
const hasEnvToken = !!process.env.FIGMA_MOCK_PROJECT_TOKEN_VALUE;
|
|
149
|
+
const shouldMock = process.env.FIGMA_MOCK_PROJECT_TOKEN !== 'false';
|
|
150
|
+
let validatedClaims;
|
|
151
|
+
if (hasEnvToken || shouldMock) {
|
|
152
|
+
log.debug('Skipping JWT validation for mock/env project token');
|
|
153
|
+
validatedClaims = parseJWTClaims(fetchedToken.token);
|
|
154
|
+
} else {
|
|
155
|
+
try {
|
|
156
|
+
validatedClaims = await validateProjectToken(fetchedToken.token, getInfraEnvironment());
|
|
157
|
+
} catch (validationError) {
|
|
158
|
+
if (validationError instanceof JWTValidationError) {
|
|
159
|
+
throw new ProjectTokenError(`Project token validation failed: ${validationError.message}`, validationError);
|
|
160
|
+
}
|
|
161
|
+
throw validationError;
|
|
97
162
|
}
|
|
98
|
-
|
|
163
|
+
}
|
|
164
|
+
if (typeof validatedClaims.exp !== 'number' || !Number.isFinite(validatedClaims.exp)) {
|
|
165
|
+
throw new ProjectTokenError('Project token missing or invalid expiration (exp) claim');
|
|
166
|
+
}
|
|
167
|
+
const expiresAt = validatedClaims.exp * 1000;
|
|
168
|
+
if (inFlightRefreshes.get(cacheKey) !== handle.promise) {
|
|
169
|
+
log.debug(`Project token refresh superseded; not persisting (cacheKey=${cacheKey})`);
|
|
170
|
+
return fetchedToken.token;
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
tokenStore.setProjectToken({
|
|
174
|
+
projectInfo,
|
|
175
|
+
token: {
|
|
176
|
+
claims: validatedClaims,
|
|
177
|
+
expiresAt,
|
|
178
|
+
tenantId: resolvedTenantId,
|
|
179
|
+
token: fetchedToken.token
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
} catch (error) {
|
|
183
|
+
// Persistence is best-effort: a failure here (disk full, permissions,
|
|
184
|
+
// corrupt conf entry) shouldn't lose the freshly-minted token. Log and
|
|
185
|
+
// populate the in-memory cache so this process can still use it.
|
|
186
|
+
log.error(`Failed to persist project token to store (cacheKey=${cacheKey}): ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
187
|
+
}
|
|
188
|
+
projectTokenCache.set(cacheKey, {
|
|
189
|
+
expiresAt,
|
|
190
|
+
token: fetchedToken.token
|
|
191
|
+
});
|
|
192
|
+
return fetchedToken.token;
|
|
193
|
+
})();
|
|
194
|
+
inFlightRefreshes.set(cacheKey, handle.promise);
|
|
195
|
+
try {
|
|
196
|
+
return await handle.promise;
|
|
197
|
+
} finally{
|
|
198
|
+
if (inFlightRefreshes.get(cacheKey) === handle.promise) {
|
|
199
|
+
inFlightRefreshes.delete(cacheKey);
|
|
99
200
|
}
|
|
100
201
|
}
|
|
101
|
-
// Ensure exp claim is present
|
|
102
|
-
if (!validatedClaims.exp) {
|
|
103
|
-
throw new ProjectTokenError('Project token missing expiration (exp) claim');
|
|
104
|
-
}
|
|
105
|
-
// Store the project token with validated expiration and claims
|
|
106
|
-
tokenStore.setProjectToken(tenantId, {
|
|
107
|
-
claims: validatedClaims,
|
|
108
|
-
expiresAt: validatedClaims.exp * 1000,
|
|
109
|
-
tenantId,
|
|
110
|
-
token: projectToken.token
|
|
111
|
-
});
|
|
112
|
-
return projectToken.token;
|
|
113
202
|
}
|
|
114
203
|
/**
|
|
115
|
-
*
|
|
204
|
+
* Force-refresh a project token, bypassing all cache layers.
|
|
116
205
|
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
206
|
+
* Invalidates the in-memory cache entry, the in-flight refresh promise (so a
|
|
207
|
+
* concurrently-running refresh that may already be returning a soon-to-be-stale
|
|
208
|
+
* token is dropped from the dedup map), and the persisted token store. Then
|
|
209
|
+
* delegates to {@link getValidProjectToken} to mint a fresh token.
|
|
119
210
|
*
|
|
120
|
-
* @param tokenStore - Token store for persisting tokens
|
|
121
|
-
* @param tenantId -
|
|
211
|
+
* @param params.tokenStore - Token store for persisting tokens
|
|
212
|
+
* @param params.tenantId - Optional tenant/CMS ID; resolved from stored bootstrap data when omitted
|
|
213
|
+
* @param params.projectInfo - Optional project scope (defaults to env vars)
|
|
122
214
|
* @returns Promise resolving to JWT token string or null if failed
|
|
123
215
|
* @throws {ProjectTokenError} If token refresh fails
|
|
124
|
-
*/ export async function refreshProjectToken(
|
|
125
|
-
|
|
126
|
-
tokenStore.
|
|
127
|
-
|
|
128
|
-
|
|
216
|
+
*/ export async function refreshProjectToken(params) {
|
|
217
|
+
const { projectInfo, tenantId, tokenStore } = params;
|
|
218
|
+
const resolvedTenantId = tenantId ?? tokenStore.getTenantId({
|
|
219
|
+
projectInfo
|
|
220
|
+
});
|
|
221
|
+
if (resolvedTenantId) {
|
|
222
|
+
const cacheKey = buildCacheKey({
|
|
223
|
+
projectInfo,
|
|
224
|
+
tenantId: resolvedTenantId
|
|
225
|
+
});
|
|
226
|
+
projectTokenCache.delete(cacheKey);
|
|
227
|
+
// Drop any in-flight refresh so getValidProjectToken below cannot return
|
|
228
|
+
// a soon-to-be-stale token via the dedup map.
|
|
229
|
+
inFlightRefreshes.delete(cacheKey);
|
|
230
|
+
}
|
|
231
|
+
tokenStore.clearProjectToken({
|
|
232
|
+
projectInfo
|
|
233
|
+
});
|
|
234
|
+
return getValidProjectToken(params);
|
|
129
235
|
}
|
|
130
236
|
|
|
131
237
|
//# sourceMappingURL=project-token.js.map
|
package/dist/auth/refresh.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ import type { FigmaTokens } from './types.js';
|
|
|
4
4
|
*/
|
|
5
5
|
export declare class TokenRefreshError extends Error {
|
|
6
6
|
statusCode?: number | undefined;
|
|
7
|
-
|
|
7
|
+
errorCode?: string | undefined;
|
|
8
|
+
constructor(message: string, statusCode?: number | undefined, errorCode?: string | undefined);
|
|
8
9
|
}
|
|
9
10
|
/**
|
|
10
11
|
* Refresh an expired OAuth2 access token using a refresh token
|