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