@payloadcms/figma 0.0.1-alpha.8 → 0.1.0-alpha.0
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 -7
- package/dist/api/control-plane.js +188 -74
- package/dist/api/error-response.d.ts +36 -0
- package/dist/api/error-response.js +66 -0
- package/dist/api/figma-api.d.ts +24 -3
- package/dist/api/figma-api.js +110 -34
- package/dist/auth/browser.d.ts +0 -1
- package/dist/auth/browser.js +0 -2
- package/dist/auth/callback-server.d.ts +19 -8
- package/dist/auth/callback-server.js +72 -32
- package/dist/auth/credentials.d.ts +20 -0
- package/dist/auth/credentials.js +19 -0
- package/dist/auth/crypto-utils.d.ts +28 -1
- package/dist/auth/crypto-utils.js +132 -23
- package/dist/auth/jwt-validator.d.ts +23 -6
- package/dist/auth/jwt-validator.js +35 -9
- package/dist/auth/oauth-flow.d.ts +19 -4
- package/dist/auth/oauth-flow.js +151 -34
- package/dist/auth/paste-code.d.ts +33 -0
- package/dist/auth/paste-code.js +87 -0
- package/dist/auth/pkce.d.ts +0 -1
- package/dist/auth/pkce.js +0 -2
- package/dist/auth/project-token.d.ts +32 -17
- package/dist/auth/project-token.js +176 -68
- package/dist/auth/refresh.d.ts +2 -2
- package/dist/auth/refresh.js +25 -14
- package/dist/auth/token-store-migration.d.ts +57 -0
- package/dist/auth/token-store-migration.js +154 -0
- package/dist/auth/token-store.d.ts +63 -98
- package/dist/auth/token-store.js +405 -124
- package/dist/auth/types.d.ts +40 -6
- package/dist/auth/types.js +1 -3
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +102 -8
- package/dist/commands/bootstrap.d.ts +17 -0
- package/dist/commands/bootstrap.js +88 -0
- package/dist/commands/build-lambda-zip.d.ts +4 -0
- package/dist/commands/build-lambda-zip.js +17 -0
- package/dist/commands/debug.d.ts +7 -0
- package/dist/commands/debug.js +178 -0
- package/dist/commands/deploy.d.ts +11 -1
- package/dist/commands/deploy.js +193 -153
- package/dist/commands/dump-tokens.d.ts +11 -0
- package/dist/commands/dump-tokens.js +67 -0
- package/dist/commands/env.d.ts +12 -0
- package/dist/commands/env.js +86 -0
- package/dist/commands/init.d.ts +9 -6
- package/dist/commands/init.js +232 -152
- package/dist/commands/list-tokens.d.ts +3 -4
- package/dist/commands/list-tokens.js +24 -11
- package/dist/commands/login.d.ts +8 -2
- package/dist/commands/login.js +34 -18
- package/dist/commands/logout.d.ts +5 -5
- package/dist/commands/logout.js +77 -17
- package/dist/commands/upgrade.d.ts +4 -0
- package/dist/commands/upgrade.js +329 -0
- package/dist/commands/upload-schema.d.ts +8 -0
- package/dist/commands/upload-schema.js +91 -0
- package/dist/config/oauth.d.ts +17 -12
- package/dist/config/oauth.js +38 -39
- package/dist/constants.d.ts +63 -19
- package/dist/constants.js +158 -20
- package/dist/db-content-api/generated/content-api-types.d.ts +7574 -0
- package/dist/db-content-api/generated/content-api-types.js +5 -0
- package/dist/db-content-api/index.d.ts +37 -0
- package/dist/db-content-api/index.js +938 -0
- package/dist/db-content-api/temp-utilities/slug.d.ts +1 -0
- package/dist/db-content-api/temp-utilities/slug.js +1 -0
- package/dist/db-content-api/temp-utilities/sorting.d.ts +2 -0
- package/dist/db-content-api/temp-utilities/sorting.js +37 -0
- package/dist/db-content-api/temp-utilities/types.d.ts +21 -0
- package/dist/db-content-api/temp-utilities/types.js +13 -0
- package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts +38 -0
- package/dist/db-content-api/temp-utilities/unwrapDocument.js +62 -0
- package/dist/db-content-api/utilities/auth.d.ts +29 -0
- package/dist/db-content-api/utilities/auth.js +82 -0
- package/dist/db-content-api/utilities/data/applyDefaults.d.ts +6 -0
- package/dist/db-content-api/utilities/data/applyDefaults.js +75 -0
- package/dist/db-content-api/utilities/data/castFieldValue.d.ts +10 -0
- package/dist/db-content-api/utilities/data/castFieldValue.js +66 -0
- package/dist/db-content-api/utilities/data/index.d.ts +48 -0
- package/dist/db-content-api/utilities/data/index.js +299 -0
- package/dist/db-content-api/utilities/data/pointShape.d.ts +3 -0
- package/dist/db-content-api/utilities/data/pointShape.js +43 -0
- package/dist/db-content-api/utilities/data/removeVirtualFields.d.ts +11 -0
- package/dist/db-content-api/utilities/data/removeVirtualFields.js +52 -0
- package/dist/db-content-api/utilities/data/richTextShape.d.ts +3 -0
- package/dist/db-content-api/utilities/data/richTextShape.js +56 -0
- package/dist/db-content-api/utilities/data/stripFields.d.ts +47 -0
- package/dist/db-content-api/utilities/data/stripFields.js +170 -0
- package/dist/db-content-api/utilities/data/transformPublishedLocale.d.ts +22 -0
- package/dist/db-content-api/utilities/data/transformPublishedLocale.js +40 -0
- package/dist/db-content-api/utilities/data/validateRelationships.d.ts +6 -0
- package/dist/db-content-api/utilities/data/validateRelationships.js +100 -0
- package/dist/db-content-api/utilities/joins.d.ts +52 -0
- package/dist/db-content-api/utilities/joins.js +137 -0
- package/dist/db-content-api/utilities/locale/index.d.ts +9 -0
- package/dist/db-content-api/utilities/locale/index.js +19 -0
- package/dist/db-content-api/utilities/meta/buildLocalizedPaths.d.ts +10 -0
- package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js +71 -0
- package/dist/db-content-api/utilities/meta/buildMeta.d.ts +41 -0
- package/dist/db-content-api/utilities/meta/buildMeta.js +39 -0
- package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts +16 -0
- package/dist/db-content-api/utilities/meta/buildPathTypes.js +243 -0
- package/dist/db-content-api/utilities/meta/buildUniquePaths.d.ts +12 -0
- package/dist/db-content-api/utilities/meta/buildUniquePaths.js +60 -0
- package/dist/db-content-api/utilities/meta/normalizeLocaleInWhere.d.ts +9 -0
- package/dist/db-content-api/utilities/meta/normalizeLocaleInWhere.js +100 -0
- package/dist/db-content-api/utilities/resolveBlocks.d.ts +19 -0
- package/dist/db-content-api/utilities/resolveBlocks.js +31 -0
- package/dist/db-content-api/utilities/schema/buildDocumentSchema.d.ts +55 -0
- package/dist/db-content-api/utilities/schema/buildDocumentSchema.js +182 -0
- package/dist/db-content-api/utilities/where.d.ts +19 -0
- package/dist/db-content-api/utilities/where.js +106 -0
- package/dist/deploy/schedule-extract-plugin.d.ts +10 -0
- package/dist/deploy/schedule-extract-plugin.js +32 -0
- package/dist/endpoints/health.d.ts +2 -0
- package/dist/endpoints/health.js +9 -0
- package/dist/endpoints/schema.d.ts +2 -0
- package/dist/endpoints/schema.js +27 -0
- package/dist/exports/client.d.ts +2 -1
- package/dist/exports/client.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/lib/download-skill.d.ts +12 -0
- package/dist/lib/download-skill.js +77 -0
- package/dist/oauth/components/FigmaAvatar/index.d.ts +3 -0
- package/dist/oauth/components/FigmaAvatar/index.js +25 -0
- package/dist/oauth/components/FigmaAvatar/index.scss +12 -0
- package/dist/oauth/components/FigmaAvatarCell/index.d.ts +4 -0
- package/dist/oauth/components/FigmaAvatarCell/index.js +23 -0
- package/dist/oauth/components/FigmaAvatarCell/index.scss +5 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.d.ts +8 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.js +35 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.scss +28 -0
- package/dist/oauth/components/LoginButton/iframeAutoLogin.d.ts +81 -0
- package/dist/oauth/components/LoginButton/iframeAutoLogin.js +168 -0
- package/dist/oauth/components/LoginButton/index.d.ts +0 -1
- package/dist/oauth/components/LoginButton/index.js +156 -18
- package/dist/oauth/components/LoginButton/index.scss +75 -3
- package/dist/oauth/components/LogoutButton/index.d.ts +0 -1
- package/dist/oauth/components/LogoutButton/index.js +20 -9
- package/dist/oauth/defaults.d.ts +3 -2
- package/dist/oauth/defaults.js +79 -12
- package/dist/oauth/endpoints/getLoginEndpoint.d.ts +0 -1
- package/dist/oauth/endpoints/getLoginEndpoint.js +87 -84
- package/dist/oauth/endpoints/getLogoutEndpoint.d.ts +0 -1
- package/dist/oauth/endpoints/getLogoutEndpoint.js +7 -6
- package/dist/oauth/endpoints/getMetaEndpoint.d.ts +0 -1
- package/dist/oauth/endpoints/getMetaEndpoint.js +18 -5
- package/dist/oauth/endpoints/getRedirectToLoginEndpoint.d.ts +0 -1
- package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js +11 -4
- package/dist/oauth/exports/client.d.ts +0 -1
- package/dist/oauth/exports/client.js +0 -2
- package/dist/oauth/hooks/afterLogout.d.ts +0 -1
- package/dist/oauth/hooks/afterLogout.js +0 -2
- package/dist/oauth/hooks/me.d.ts +0 -1
- package/dist/oauth/hooks/me.js +0 -2
- package/dist/oauth/hooks/refresh.d.ts +0 -1
- package/dist/oauth/hooks/refresh.js +2 -3
- package/dist/oauth/index.d.ts +0 -1
- package/dist/oauth/index.js +27 -7
- package/dist/oauth/strategy/index.d.ts +0 -3
- package/dist/oauth/strategy/index.js +55 -34
- package/dist/oauth/types.d.ts +23 -7
- package/dist/oauth/types.js +0 -2
- package/dist/oauth/utilities/buildUnauthorizedRedirect.d.ts +14 -0
- package/dist/oauth/utilities/buildUnauthorizedRedirect.js +28 -0
- package/dist/oauth/utilities/clearCookie.d.ts +0 -1
- package/dist/oauth/utilities/clearCookie.js +5 -3
- package/dist/oauth/utilities/createCookieOptions.d.ts +0 -1
- package/dist/oauth/utilities/createCookieOptions.js +9 -4
- package/dist/oauth/utilities/createDebugLogger.d.ts +0 -1
- package/dist/oauth/utilities/createDebugLogger.js +0 -2
- package/dist/oauth/utilities/establishSession.d.ts +22 -0
- package/dist/oauth/utilities/establishSession.js +80 -0
- package/dist/oauth/utilities/exchangeCodeForAccessToken.d.ts +23 -0
- package/dist/oauth/utilities/exchangeCodeForAccessToken.js +26 -0
- package/dist/oauth/utilities/extractOrigin.d.ts +0 -1
- package/dist/oauth/utilities/extractOrigin.js +0 -2
- package/dist/oauth/utilities/figmaHostnames.d.ts +2 -0
- package/dist/oauth/utilities/figmaHostnames.js +24 -0
- package/dist/oauth/utilities/getAdminCollectionSlug.d.ts +0 -1
- package/dist/oauth/utilities/getAdminCollectionSlug.js +0 -2
- package/dist/oauth/utilities/getAuthorizeURL.d.ts +65 -2
- package/dist/oauth/utilities/getAuthorizeURL.js +57 -4
- package/dist/oauth/utilities/getCookieExpiration.d.ts +0 -1
- package/dist/oauth/utilities/getCookieExpiration.js +0 -2
- package/dist/oauth/utilities/getSecondsFromTokenExp.d.ts +0 -1
- package/dist/oauth/utilities/getSecondsFromTokenExp.js +0 -2
- package/dist/oauth/utilities/getTokenExp.d.ts +0 -1
- package/dist/oauth/utilities/getTokenExp.js +0 -2
- package/dist/oauth/utilities/getUsernameField.d.ts +0 -1
- package/dist/oauth/utilities/getUsernameField.js +0 -2
- package/dist/oauth/utilities/hasUserTokenPropsChanged.d.ts +0 -1
- package/dist/oauth/utilities/hasUserTokenPropsChanged.js +0 -2
- package/dist/oauth/utilities/isAbsoluteURL.d.ts +1 -0
- package/dist/oauth/utilities/isAbsoluteURL.js +1 -0
- package/dist/oauth/utilities/isDuplicateKeyError.d.ts +6 -0
- package/dist/oauth/utilities/isDuplicateKeyError.js +12 -0
- package/dist/oauth/utilities/mergeHeaders.d.ts +0 -1
- package/dist/oauth/utilities/mergeHeaders.js +0 -2
- package/dist/oauth/utilities/refreshTokens.d.ts +0 -1
- package/dist/oauth/utilities/refreshTokens.js +21 -13
- package/dist/oauth/utilities/withPartitionedCookie.d.ts +19 -0
- package/dist/oauth/utilities/withPartitionedCookie.js +26 -0
- package/dist/oauth/utils/getSearchParam.d.ts +17 -0
- package/dist/oauth/utils/getSearchParam.js +22 -0
- package/dist/plugin/adapter.d.ts +0 -1
- package/dist/plugin/adapter.js +0 -2
- package/dist/plugin/auth-preflight.d.ts +7 -0
- package/dist/plugin/auth-preflight.js +18 -0
- package/dist/plugin/bootstrap-preflight.d.ts +22 -0
- package/dist/plugin/bootstrap-preflight.js +43 -0
- package/dist/plugin/build-config.d.ts +27 -15
- package/dist/plugin/build-config.js +381 -18
- package/dist/plugin/dev-cookie-names.d.ts +13 -0
- package/dist/plugin/dev-cookie-names.js +17 -0
- package/dist/scss.d.js +2 -0
- package/dist/storage-content-api/api-types.d.ts +183 -0
- package/dist/storage-content-api/api-types.js +4 -0
- package/dist/storage-content-api/client-uploads/generate.d.ts +14 -0
- package/dist/storage-content-api/client-uploads/generate.js +69 -0
- package/dist/storage-content-api/client.d.ts +5 -0
- package/dist/storage-content-api/client.js +37 -0
- package/dist/storage-content-api/generateURL.d.ts +6 -0
- package/dist/storage-content-api/generateURL.js +6 -0
- package/dist/storage-content-api/handleDelete.d.ts +7 -0
- package/dist/storage-content-api/handleDelete.js +15 -0
- package/dist/storage-content-api/handleUpload.d.ts +10 -0
- package/dist/storage-content-api/handleUpload.js +162 -0
- package/dist/storage-content-api/index.d.ts +4 -0
- package/dist/storage-content-api/index.js +37 -0
- package/dist/storage-content-api/staticHandler.d.ts +9 -0
- package/dist/storage-content-api/staticHandler.js +61 -0
- package/dist/storage-content-api/types.d.ts +9 -0
- package/dist/storage-content-api/types.js +1 -0
- package/dist/storage-content-api/utilities/getSafeFilename.d.ts +11 -0
- package/dist/storage-content-api/utilities/getSafeFilename.js +59 -0
- package/dist/storage-content-api/utilities/index.d.ts +2 -0
- package/dist/storage-content-api/utilities/index.js +2 -0
- package/dist/storage-content-api/utilities/parseUploadReference.d.ts +17 -0
- package/dist/storage-content-api/utilities/parseUploadReference.js +27 -0
- package/dist/templates/.env.example +5 -0
- package/dist/templates/README.md +19 -0
- package/dist/types/config.d.ts +2 -2
- package/dist/types/config.js +0 -4
- package/dist/types.d.ts +10 -2
- package/dist/types.js +0 -2
- package/dist/utils/adapters/nextjs.d.ts +8 -0
- package/dist/utils/adapters/nextjs.js +61 -0
- package/dist/utils/adapters/nitro.d.ts +8 -0
- package/dist/utils/adapters/nitro.js +172 -0
- package/dist/utils/adapters/vite.d.ts +9 -0
- package/dist/utils/adapters/vite.js +31 -0
- package/dist/utils/asset-collection.d.ts +27 -7
- package/dist/utils/asset-collection.js +59 -32
- package/dist/utils/build-detection.d.ts +5 -12
- package/dist/utils/build-detection.js +74 -13
- package/dist/utils/build-lambda-zip.d.ts +25 -0
- package/dist/utils/build-lambda-zip.js +90 -0
- package/dist/utils/cache-bootstrap.d.ts +7 -0
- package/dist/utils/cache-bootstrap.js +16 -0
- package/dist/utils/config.d.ts +0 -1
- package/dist/utils/config.js +1 -3
- package/dist/utils/deploy-adapter.d.ts +45 -0
- package/dist/utils/deploy-adapter.js +56 -0
- package/dist/utils/download-template.d.ts +9 -2
- package/dist/utils/download-template.js +24 -20
- package/dist/utils/env-management.d.ts +24 -8
- package/dist/utils/env-management.js +119 -66
- package/dist/utils/format-env-suffix.d.ts +11 -0
- package/dist/utils/format-env-suffix.js +11 -0
- package/dist/utils/format.d.ts +0 -1
- package/dist/utils/format.js +0 -2
- package/dist/utils/formatter.d.ts +0 -1
- package/dist/utils/formatter.js +23 -13
- package/dist/utils/fs-utils.d.ts +12 -0
- package/dist/utils/fs-utils.js +55 -0
- package/dist/utils/git.d.ts +0 -1
- package/dist/utils/git.js +0 -2
- package/dist/utils/handle-upgrade.d.ts +8 -0
- package/dist/utils/handle-upgrade.js +39 -0
- package/dist/utils/is-debug.d.ts +0 -1
- package/dist/utils/is-debug.js +0 -2
- package/dist/utils/lambda-config.d.ts +3 -2
- package/dist/utils/lambda-config.js +75 -80
- package/dist/utils/load-payload-config.d.ts +9 -0
- package/dist/utils/load-payload-config.js +27 -0
- package/dist/utils/log.d.ts +0 -1
- package/dist/utils/log.js +0 -2
- package/dist/utils/messages.d.ts +1 -3
- package/dist/utils/messages.js +47 -13
- package/dist/utils/package-manager.d.ts +24 -1
- package/dist/utils/package-manager.js +53 -2
- package/dist/utils/parse-template-spec.d.ts +11 -0
- package/dist/utils/parse-template-spec.js +60 -0
- package/dist/utils/payload-config-ast.d.ts +27 -7
- package/dist/utils/payload-config-ast.js +106 -60
- package/dist/utils/payload-config-finder.d.ts +2 -3
- package/dist/utils/payload-config-finder.js +48 -11
- package/dist/utils/payload-config-modifier.d.ts +1 -2
- package/dist/utils/payload-config-modifier.js +114 -68
- package/dist/utils/payload-package-check.d.ts +28 -3
- package/dist/utils/payload-package-check.js +90 -31
- package/dist/utils/project.d.ts +8 -4
- package/dist/utils/project.js +63 -37
- package/dist/utils/resolve-environment.d.ts +13 -0
- package/dist/utils/resolve-environment.js +29 -0
- package/dist/utils/s3-upload.d.ts +7 -3
- package/dist/utils/s3-upload.js +44 -9
- package/dist/utils/token-display.d.ts +5 -2
- package/dist/utils/token-display.js +49 -24
- package/dist/utils/typescript-validator.d.ts +0 -1
- package/dist/utils/typescript-validator.js +4 -8
- package/dist/utils/version-check.d.ts +2 -0
- package/dist/utils/version-check.js +43 -0
- package/package.json +47 -16
- 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,11 +1,12 @@
|
|
|
1
|
+
import type { Environment } from '../constants.js';
|
|
1
2
|
import type { JWTPayload } from './types.js';
|
|
2
3
|
/**
|
|
3
4
|
* JWT validation error with specific error codes
|
|
4
5
|
*/
|
|
5
6
|
export declare class JWTValidationError extends Error {
|
|
6
|
-
code: 'EXPIRED' | 'JWKS_FETCH_FAILED' | 'MISSING_KID' | 'SIGNATURE_INVALID';
|
|
7
|
+
code: 'AUDIENCE_INVALID' | 'EXPIRED' | 'JWKS_FETCH_FAILED' | 'MISSING_KID' | 'SIGNATURE_INVALID' | 'TOKEN_CLAIMS_INVALID';
|
|
7
8
|
cause?: Error | undefined;
|
|
8
|
-
constructor(message: string, code: 'EXPIRED' | 'JWKS_FETCH_FAILED' | 'MISSING_KID' | 'SIGNATURE_INVALID', cause?: Error | undefined);
|
|
9
|
+
constructor(message: string, code: 'AUDIENCE_INVALID' | 'EXPIRED' | 'JWKS_FETCH_FAILED' | 'MISSING_KID' | 'SIGNATURE_INVALID' | 'TOKEN_CLAIMS_INVALID', cause?: Error | undefined);
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
12
|
* Validate a project token JWT
|
|
@@ -22,12 +23,29 @@ export declare class JWTValidationError extends Error {
|
|
|
22
23
|
* - Validates standard claims (exp, iat, nbf)
|
|
23
24
|
* - Handles clock skew tolerance
|
|
24
25
|
*
|
|
25
|
-
* @param token - JWT token string
|
|
26
|
-
* @param environment - Figma environment ('production' or 'staging')
|
|
26
|
+
* @param params.token - JWT token string
|
|
27
|
+
* @param params.environment - Figma environment ('production' or 'staging')
|
|
28
|
+
* @param params.audience - Expected `aud` claim (the tenant's contentSystemId);
|
|
29
|
+
* when provided, jose rejects tokens whose `aud` does not match
|
|
27
30
|
* @returns Promise resolving to validated JWT payload
|
|
28
31
|
* @throws {JWTValidationError} If validation fails
|
|
29
32
|
*/
|
|
30
|
-
export declare function validateProjectToken(
|
|
33
|
+
export declare function validateProjectToken(params: {
|
|
34
|
+
/** Expected `aud` claim — the tenant's contentSystemId. Enforced when provided. */
|
|
35
|
+
audience?: string;
|
|
36
|
+
environment: Environment;
|
|
37
|
+
token: string;
|
|
38
|
+
}): Promise<JWTPayload>;
|
|
39
|
+
export declare function validatePayloadAdminToken(params: {
|
|
40
|
+
audience: string;
|
|
41
|
+
environment: Environment;
|
|
42
|
+
token: string;
|
|
43
|
+
}): Promise<JWTPayload>;
|
|
44
|
+
export declare function validateContentApiToken(params: {
|
|
45
|
+
audience: string;
|
|
46
|
+
environment: Environment;
|
|
47
|
+
token: string;
|
|
48
|
+
}): Promise<JWTPayload>;
|
|
31
49
|
/**
|
|
32
50
|
* Clear JWKS cache (useful for testing or forcing refresh)
|
|
33
51
|
*
|
|
@@ -38,4 +56,3 @@ export declare function validateProjectToken(token: string, environment: 'produc
|
|
|
38
56
|
* - Clearing state between test runs
|
|
39
57
|
*/
|
|
40
58
|
export declare function clearJWKSCache(): void;
|
|
41
|
-
//# sourceMappingURL=jwt-validator.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRemoteJWKSet, jwtVerify } from 'jose';
|
|
2
|
-
import { JWKSMultipleMatchingKeys, JWKSNoMatchingKey, JWSInvalid, JWSSignatureVerificationFailed, JWTExpired } from 'jose/errors';
|
|
3
|
-
import {
|
|
2
|
+
import { JWKSMultipleMatchingKeys, JWKSNoMatchingKey, JWSInvalid, JWSSignatureVerificationFailed, JWTClaimValidationFailed, JWTExpired } from 'jose/errors';
|
|
3
|
+
import { getEnvConfig } from '../constants.js';
|
|
4
4
|
/**
|
|
5
5
|
* JWT validation error with specific error codes
|
|
6
6
|
*/ export class JWTValidationError extends Error {
|
|
@@ -28,7 +28,7 @@ import { getJWKSUri } from '../constants.js';
|
|
|
28
28
|
* @param environment - Figma environment ('production' or 'staging')
|
|
29
29
|
* @returns JWKS resolver function
|
|
30
30
|
*/ function getJWKSResolver(environment) {
|
|
31
|
-
const jwksUri =
|
|
31
|
+
const jwksUri = getEnvConfig(environment).jwksUri;
|
|
32
32
|
if (!jwksResolvers.has(jwksUri)) {
|
|
33
33
|
jwksResolvers.set(jwksUri, createRemoteJWKSet(new URL(jwksUri), {
|
|
34
34
|
cacheMaxAge: 24 * 60 * 60 * 1000,
|
|
@@ -52,15 +52,21 @@ import { getJWKSUri } from '../constants.js';
|
|
|
52
52
|
* - Validates standard claims (exp, iat, nbf)
|
|
53
53
|
* - Handles clock skew tolerance
|
|
54
54
|
*
|
|
55
|
-
* @param token - JWT token string
|
|
56
|
-
* @param environment - Figma environment ('production' or 'staging')
|
|
55
|
+
* @param params.token - JWT token string
|
|
56
|
+
* @param params.environment - Figma environment ('production' or 'staging')
|
|
57
|
+
* @param params.audience - Expected `aud` claim (the tenant's contentSystemId);
|
|
58
|
+
* when provided, jose rejects tokens whose `aud` does not match
|
|
57
59
|
* @returns Promise resolving to validated JWT payload
|
|
58
60
|
* @throws {JWTValidationError} If validation fails
|
|
59
|
-
*/ export async function validateProjectToken(
|
|
61
|
+
*/ export async function validateProjectToken(params) {
|
|
62
|
+
const { audience, environment, token } = params;
|
|
60
63
|
try {
|
|
61
64
|
const JWKS = getJWKSResolver(environment);
|
|
62
65
|
const { payload } = await jwtVerify(token, JWKS, {
|
|
63
|
-
clockTolerance:
|
|
66
|
+
clockTolerance: 30,
|
|
67
|
+
...audience ? {
|
|
68
|
+
audience
|
|
69
|
+
} : {}
|
|
64
70
|
});
|
|
65
71
|
return payload;
|
|
66
72
|
} catch (error) {
|
|
@@ -86,6 +92,10 @@ import { getJWKSUri } from '../constants.js';
|
|
|
86
92
|
if (error instanceof JWSInvalid) {
|
|
87
93
|
throw new JWTValidationError('Invalid JWT structure - missing required header fields (kid or alg)', 'MISSING_KID', error);
|
|
88
94
|
}
|
|
95
|
+
// Audience mismatch (or missing `aud` when an audience is required)
|
|
96
|
+
if (error instanceof JWTClaimValidationFailed && error.claim === 'aud') {
|
|
97
|
+
throw new JWTValidationError('Token audience does not match this tenant', 'AUDIENCE_INVALID', error);
|
|
98
|
+
}
|
|
89
99
|
// Network or fetch errors (not jose errors, generic Error instances)
|
|
90
100
|
if (error instanceof Error) {
|
|
91
101
|
const message = error.message;
|
|
@@ -98,6 +108,24 @@ import { getJWKSUri } from '../constants.js';
|
|
|
98
108
|
throw new JWTValidationError(`JWT validation failed: ${message}`, 'SIGNATURE_INVALID', error instanceof Error ? error : undefined);
|
|
99
109
|
}
|
|
100
110
|
}
|
|
111
|
+
export async function validatePayloadAdminToken(params) {
|
|
112
|
+
const payload = await validateProjectToken({
|
|
113
|
+
...params,
|
|
114
|
+
audience: `eid_${params.audience}`
|
|
115
|
+
});
|
|
116
|
+
if (typeof payload.sub !== 'string' || typeof payload.email !== 'string') {
|
|
117
|
+
throw new JWTValidationError('Payload Admin token claims are invalid', 'TOKEN_CLAIMS_INVALID');
|
|
118
|
+
}
|
|
119
|
+
return payload;
|
|
120
|
+
}
|
|
121
|
+
export async function validateContentApiToken(params) {
|
|
122
|
+
// Content API tokens are issued by the content-system-scoped endpoint, which
|
|
123
|
+
// prefixes the `aud` with `csid_` (mirrors the `eid_` admin-token scoping).
|
|
124
|
+
return validateProjectToken({
|
|
125
|
+
...params,
|
|
126
|
+
audience: `csid_${params.audience}`
|
|
127
|
+
});
|
|
128
|
+
}
|
|
101
129
|
/**
|
|
102
130
|
* Clear JWKS cache (useful for testing or forcing refresh)
|
|
103
131
|
*
|
|
@@ -109,5 +137,3 @@ import { getJWKSUri } from '../constants.js';
|
|
|
109
137
|
*/ export function clearJWKSCache() {
|
|
110
138
|
jwksResolvers.clear();
|
|
111
139
|
}
|
|
112
|
-
|
|
113
|
-
//# sourceMappingURL=jwt-validator.js.map
|
|
@@ -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,20 @@ 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
|
|
62
|
-
|
|
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>;
|
package/dist/auth/oauth-flow.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
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
|
-
import { CallbackServer } from './callback-server.js';
|
|
6
|
+
import { CallbackError, CallbackServer } from './callback-server.js';
|
|
7
|
+
import { parsePastedCode, validatePastedCode } from './paste-code.js';
|
|
7
8
|
import { generatePKCEPair } from './pkce.js';
|
|
8
|
-
import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
9
|
+
import { exchangeCodeForTokens, refreshAccessToken, TokenRefreshError } from './refresh.js';
|
|
9
10
|
/**
|
|
10
11
|
* Error during OAuth flow
|
|
11
12
|
*/ export class OAuthFlowError extends Error {
|
|
@@ -32,16 +33,17 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
|
32
33
|
* @throws OAuthFlowError if any step fails
|
|
33
34
|
*/ export async function executeOAuthFlow(tokenStore, options = {}) {
|
|
34
35
|
// Check if OAuth flow should be mocked
|
|
35
|
-
// Default to
|
|
36
|
-
const shouldMock = process.env.FIGMA_MOCK_OAUTH
|
|
36
|
+
// Default to false for OAuth
|
|
37
|
+
const shouldMock = process.env.FIGMA_MOCK_OAUTH === 'true';
|
|
38
|
+
const oauthConfig = getOAuthConfig();
|
|
37
39
|
if (shouldMock) {
|
|
38
40
|
// MOCK IMPLEMENTATION: Return mock tokens for testing
|
|
39
|
-
log.debug('Using mock OAuth flow (FIGMA_MOCK_OAUTH
|
|
41
|
+
log.debug('Using mock OAuth flow (FIGMA_MOCK_OAUTH = true)');
|
|
40
42
|
const mockTokens = {
|
|
41
43
|
accessToken: 'figt_mock_access_token_' + crypto.randomBytes(16).toString('hex'),
|
|
42
44
|
expiresAt: Date.now() + 2 * 60 * 60 * 1000,
|
|
43
45
|
refreshToken: 'figt_mock_refresh_token_' + crypto.randomBytes(16).toString('hex'),
|
|
44
|
-
scopes: options.scopes ||
|
|
46
|
+
scopes: options.scopes || oauthConfig.scopes,
|
|
45
47
|
tokenType: 'Bearer'
|
|
46
48
|
};
|
|
47
49
|
// Store mock tokens
|
|
@@ -52,28 +54,30 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
|
52
54
|
};
|
|
53
55
|
}
|
|
54
56
|
// REAL OAUTH IMPLEMENTATION
|
|
55
|
-
const { clientId =
|
|
57
|
+
const { clientId = oauthConfig.clientId, fallbackPorts, port, redirectUri = oauthConfig.redirectUri, scopes = oauthConfig.scopes, timeoutMs = 120000 } = options;
|
|
56
58
|
// Generate PKCE pair for enhanced security
|
|
57
59
|
const { codeChallenge, codeChallengeMethod, codeVerifier } = generatePKCEPair();
|
|
58
60
|
// Generate random state for CSRF protection
|
|
59
61
|
const state = crypto.randomBytes(32).toString('base64url');
|
|
60
62
|
// Create callback server
|
|
61
63
|
const callbackServer = new CallbackServer({
|
|
64
|
+
fallbackPorts,
|
|
62
65
|
port,
|
|
63
66
|
timeoutMs
|
|
64
67
|
});
|
|
65
68
|
try {
|
|
66
69
|
// Start waiting for callback (this starts the server and captures actual port)
|
|
67
70
|
const callbackPromise = callbackServer.waitForCallback(state);
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
callbackPromise.catch(()=>{
|
|
72
|
+
// The callback promise is awaited below; avoid an unhandled rejection if startup fails early.
|
|
73
|
+
});
|
|
70
74
|
// Get the actual port (may differ from preferred if that was in use)
|
|
71
|
-
const actualPort = callbackServer.
|
|
75
|
+
const actualPort = await callbackServer.waitUntilReady();
|
|
72
76
|
// Build redirect URI with actual port
|
|
73
|
-
const actualRedirectUri = redirectUri
|
|
77
|
+
const actualRedirectUri = replaceRedirectUriPort(redirectUri, actualPort);
|
|
74
78
|
// Build authorization URL
|
|
75
79
|
const authUrl = buildAuthorizationUrl({
|
|
76
|
-
authorizationUrl:
|
|
80
|
+
authorizationUrl: oauthConfig.authorizationUrl,
|
|
77
81
|
clientId,
|
|
78
82
|
codeChallenge,
|
|
79
83
|
codeChallengeMethod,
|
|
@@ -84,28 +88,36 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
|
84
88
|
// Prompt user to open browser
|
|
85
89
|
const shouldOpenBrowser = await p.confirm({
|
|
86
90
|
initialValue: true,
|
|
87
|
-
message: '
|
|
91
|
+
message: 'Open browser to authenticate with Figma?'
|
|
88
92
|
});
|
|
89
93
|
if (p.isCancel(shouldOpenBrowser)) {
|
|
90
94
|
throw new OAuthFlowError('Authentication cancelled by user');
|
|
91
95
|
}
|
|
96
|
+
let browserOpened = false;
|
|
92
97
|
if (shouldOpenBrowser) {
|
|
93
|
-
// Try to open browser, but don't fail if it doesn't work
|
|
94
98
|
try {
|
|
95
99
|
await openBrowser(authUrl);
|
|
100
|
+
browserOpened = true;
|
|
96
101
|
} catch (_error) {
|
|
97
|
-
// Browser opening failed, show URL for manual opening
|
|
98
102
|
log.warning('Could not open browser automatically.');
|
|
99
|
-
log.info(`Please open this URL in your browser:`);
|
|
100
|
-
log.info(` ${authUrl}`);
|
|
101
103
|
}
|
|
104
|
+
}
|
|
105
|
+
let code;
|
|
106
|
+
if (browserOpened) {
|
|
107
|
+
// Browser launched locally; the localhost listener receives the callback.
|
|
108
|
+
code = (await callbackPromise).code;
|
|
102
109
|
} else {
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
110
|
+
// No local browser (user declined, or open() failed — e.g. a remote devbox).
|
|
111
|
+
// Show the URL to open manually and accept the redirected code pasted back,
|
|
112
|
+
// while the localhost listener keeps running in case it can still receive it.
|
|
113
|
+
// p.log.step directly (not log.info) to avoid bolding the URL.
|
|
114
|
+
p.log.step(`Open this URL to authenticate:\n\n ${authUrl}`);
|
|
115
|
+
code = await waitForCallbackOrPastedCode({
|
|
116
|
+
callbackPromise,
|
|
117
|
+
callbackServer,
|
|
118
|
+
expectedState: state
|
|
119
|
+
});
|
|
106
120
|
}
|
|
107
|
-
// Wait for callback
|
|
108
|
-
const { code } = await callbackPromise;
|
|
109
121
|
// Exchange authorization code for tokens
|
|
110
122
|
let tokens;
|
|
111
123
|
try {
|
|
@@ -142,28 +154,133 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
|
142
154
|
* refreshes using the refresh token. If no tokens exist, returns null.
|
|
143
155
|
*
|
|
144
156
|
* @param tokenStore - Token store to use
|
|
145
|
-
* @returns Promise resolving to access token or null if no valid tokens
|
|
157
|
+
* @returns Promise resolving to AuthCredential (wrapped access token) or null if no valid tokens
|
|
146
158
|
* @throws OAuthFlowError if refresh fails
|
|
147
|
-
*/ export async function
|
|
159
|
+
*/ export async function getValidOAuthAccessToken(tokenStore) {
|
|
148
160
|
// Check if we have valid tokens
|
|
149
|
-
if (tokenStore.
|
|
150
|
-
|
|
161
|
+
if (tokenStore.hasValidOauthToken()) {
|
|
162
|
+
const token = tokenStore.getCurrentOauthToken();
|
|
163
|
+
return token ? {
|
|
164
|
+
type: 'oauth',
|
|
165
|
+
token
|
|
166
|
+
} : null;
|
|
151
167
|
}
|
|
152
168
|
// Check if we have a refresh token
|
|
153
|
-
const refreshToken = tokenStore.
|
|
169
|
+
const refreshToken = tokenStore.getCurrentRefreshToken();
|
|
154
170
|
if (!refreshToken) {
|
|
155
171
|
return null;
|
|
156
172
|
}
|
|
157
|
-
// Try to refresh
|
|
173
|
+
// Try to refresh (with one retry for transient auth errors)
|
|
158
174
|
try {
|
|
159
175
|
const tokens = await refreshAccessToken(refreshToken);
|
|
160
176
|
tokenStore.setTokens(tokens);
|
|
161
|
-
return
|
|
177
|
+
return {
|
|
178
|
+
type: 'oauth',
|
|
179
|
+
token: tokens.accessToken
|
|
180
|
+
};
|
|
162
181
|
} catch (error) {
|
|
163
|
-
|
|
164
|
-
|
|
182
|
+
const isAuthFailure = error instanceof TokenRefreshError && (error.statusCode === 401 || error.statusCode === 403 || error.statusCode === 400 && error.errorCode === 'invalid_grant');
|
|
183
|
+
if (isAuthFailure) {
|
|
184
|
+
// Retry once — a transient 401 (e.g. misconfigured proxy) shouldn't wipe tokens
|
|
185
|
+
try {
|
|
186
|
+
const tokens = await refreshAccessToken(refreshToken);
|
|
187
|
+
tokenStore.setTokens(tokens);
|
|
188
|
+
return {
|
|
189
|
+
type: 'oauth',
|
|
190
|
+
token: tokens.accessToken
|
|
191
|
+
};
|
|
192
|
+
} catch {
|
|
193
|
+
// Retry also failed — token is genuinely revoked
|
|
194
|
+
tokenStore.clearTokens();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
165
197
|
throw new OAuthFlowError('Failed to refresh access token', error instanceof Error ? error : undefined);
|
|
166
198
|
}
|
|
167
199
|
}
|
|
168
|
-
|
|
169
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Get a valid auth credential, checking process.env for plan access token
|
|
202
|
+
* first before checking tokenStore for OAuth tokens.
|
|
203
|
+
* *
|
|
204
|
+
* @param tokenStore - Token store to use for OAuth tokens
|
|
205
|
+
* @returns Promise resolving to AuthCredential or null
|
|
206
|
+
*/ export async function getValidCredential(tokenStore) {
|
|
207
|
+
const envFigmaAccessToken = process.env.FIGMA_ACCESS_TOKEN;
|
|
208
|
+
if (envFigmaAccessToken) {
|
|
209
|
+
log.debug('Using FIGMA_ACCESS_TOKEN env var override; skipping stored OAuth tokens');
|
|
210
|
+
return {
|
|
211
|
+
type: 'plan_access_token',
|
|
212
|
+
token: envFigmaAccessToken
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
return getValidOAuthAccessToken(tokenStore);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Like getValidCredential but returns null instead of throwing on refresh failure.
|
|
219
|
+
* Use in commands that want to fall through to a login prompt on failure.
|
|
220
|
+
*/ export async function tryGetCredential(tokenStore) {
|
|
221
|
+
try {
|
|
222
|
+
return await getValidCredential(tokenStore);
|
|
223
|
+
} catch {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Race the localhost callback listener against a pasted-code prompt.
|
|
229
|
+
*
|
|
230
|
+
* Used when no local browser was opened (remote/headless environments). Whichever
|
|
231
|
+
* settles first wins: if the listener receives the callback, the paste prompt is
|
|
232
|
+
* aborted; if the user pastes first, the listener is stopped. The listener's own
|
|
233
|
+
* timeout is non-fatal here — the user may take a while approving in the browser.
|
|
234
|
+
*
|
|
235
|
+
* @returns The authorization code from whichever source won
|
|
236
|
+
* @throws OAuthFlowError if the user cancels the paste prompt or the pasted value is invalid
|
|
237
|
+
*/ async function waitForCallbackOrPastedCode({ callbackPromise, callbackServer, expectedState }) {
|
|
238
|
+
const abortController = new AbortController();
|
|
239
|
+
const listenerBranch = callbackPromise.then((result)=>{
|
|
240
|
+
// Listener won — tear down the paste prompt.
|
|
241
|
+
abortController.abort();
|
|
242
|
+
return result.code;
|
|
243
|
+
}, (error)=>{
|
|
244
|
+
// A timeout (or an unreachable listener on a remote box, which surfaces as a
|
|
245
|
+
// timeout) is non-fatal here — the user can still paste. Any other callback
|
|
246
|
+
// error means the browser actually reached the listener (denied consent, bad
|
|
247
|
+
// request, state mismatch), so surface it instead of hanging silently on the
|
|
248
|
+
// paste prompt.
|
|
249
|
+
if (error instanceof CallbackError && error.code === 'timeout') {
|
|
250
|
+
return new Promise(()=>{});
|
|
251
|
+
}
|
|
252
|
+
abortController.abort();
|
|
253
|
+
throw error;
|
|
254
|
+
});
|
|
255
|
+
const pasteBranch = (async ()=>{
|
|
256
|
+
// @clack/prompts TextOptions doesn't expose `signal` in its public type, but the
|
|
257
|
+
// underlying @clack/core PromptOptions does. Cast to reach the runtime capability.
|
|
258
|
+
const textOpts = {
|
|
259
|
+
message: 'Paste the redirect URL or code (optional):',
|
|
260
|
+
signal: abortController.signal,
|
|
261
|
+
validate: (value)=>validatePastedCode(value ?? '')
|
|
262
|
+
};
|
|
263
|
+
const pasted = await p.text(textOpts);
|
|
264
|
+
if (p.isCancel(pasted)) {
|
|
265
|
+
throw new OAuthFlowError('Authentication cancelled by user');
|
|
266
|
+
}
|
|
267
|
+
// Paste won — stop the listener before exchanging.
|
|
268
|
+
callbackServer.stop();
|
|
269
|
+
try {
|
|
270
|
+
return parsePastedCode(pasted, expectedState);
|
|
271
|
+
} catch (error) {
|
|
272
|
+
throw new OAuthFlowError(error instanceof Error ? error.message : 'Invalid pasted authorization code', error instanceof Error ? error : undefined);
|
|
273
|
+
}
|
|
274
|
+
})();
|
|
275
|
+
// Avoid an unhandled rejection when the paste prompt is aborted after the listener wins.
|
|
276
|
+
pasteBranch.catch(()=>{});
|
|
277
|
+
return Promise.race([
|
|
278
|
+
listenerBranch,
|
|
279
|
+
pasteBranch
|
|
280
|
+
]);
|
|
281
|
+
}
|
|
282
|
+
function replaceRedirectUriPort(redirectUri, port) {
|
|
283
|
+
const url = new URL(redirectUri);
|
|
284
|
+
url.port = String(port);
|
|
285
|
+
return url.toString();
|
|
286
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error parsing a pasted authorization code or redirect URL.
|
|
3
|
+
*/
|
|
4
|
+
export declare class PastedCodeError extends Error {
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Parse a value the user pasted back after completing OAuth in their browser.
|
|
9
|
+
*
|
|
10
|
+
* Accepts either the full redirect URL (e.g.
|
|
11
|
+
* `http://localhost:34462/callback?code=...&state=...`) or a bare authorization
|
|
12
|
+
* code. When a URL is pasted, the `state` is validated against the value the CLI
|
|
13
|
+
* generated (CSRF protection); when a bare code is pasted, no state check is
|
|
14
|
+
* possible and PKCE alone gates the subsequent token exchange.
|
|
15
|
+
*
|
|
16
|
+
* @param input - Raw pasted text
|
|
17
|
+
* @param expectedState - The state value the CLI generated for this flow
|
|
18
|
+
* @returns The authorization code
|
|
19
|
+
* @throws PastedCodeError if the input is empty, is a URL without a code, or has a mismatched state
|
|
20
|
+
*/
|
|
21
|
+
export declare function parsePastedCode(input: string, expectedState: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Structural validation for use as a `@clack/prompts` `text` validator.
|
|
24
|
+
*
|
|
25
|
+
* Returns `undefined` when the input could yield a code (so the prompt accepts it),
|
|
26
|
+
* or a human-readable message to re-prompt. Intentionally does NOT validate `state`
|
|
27
|
+
* — a state mismatch is a hard failure handled after the prompt resolves, not a
|
|
28
|
+
* re-prompt condition.
|
|
29
|
+
*
|
|
30
|
+
* @param input - Current prompt value
|
|
31
|
+
* @returns Error message string, or undefined if structurally valid
|
|
32
|
+
*/
|
|
33
|
+
export declare function validatePastedCode(input: string): string | undefined;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error parsing a pasted authorization code or redirect URL.
|
|
3
|
+
*/ export class PastedCodeError extends Error {
|
|
4
|
+
constructor(message){
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = 'PastedCodeError';
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
const NO_CODE_MESSAGE = 'That URL has no "code" parameter. Paste the full redirect URL or just the code.';
|
|
10
|
+
function parsePasteInput(input) {
|
|
11
|
+
const trimmed = input.trim();
|
|
12
|
+
if (!trimmed) {
|
|
13
|
+
return {
|
|
14
|
+
kind: 'empty'
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
let url;
|
|
18
|
+
try {
|
|
19
|
+
url = new URL(trimmed);
|
|
20
|
+
} catch {
|
|
21
|
+
return {
|
|
22
|
+
code: trimmed,
|
|
23
|
+
kind: 'bare-code'
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const code = url.searchParams.get('code');
|
|
27
|
+
if (!code) {
|
|
28
|
+
return {
|
|
29
|
+
kind: 'url-missing-code'
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
code,
|
|
34
|
+
kind: 'url',
|
|
35
|
+
state: url.searchParams.get('state')
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Parse a value the user pasted back after completing OAuth in their browser.
|
|
40
|
+
*
|
|
41
|
+
* Accepts either the full redirect URL (e.g.
|
|
42
|
+
* `http://localhost:34462/callback?code=...&state=...`) or a bare authorization
|
|
43
|
+
* code. When a URL is pasted, the `state` is validated against the value the CLI
|
|
44
|
+
* generated (CSRF protection); when a bare code is pasted, no state check is
|
|
45
|
+
* possible and PKCE alone gates the subsequent token exchange.
|
|
46
|
+
*
|
|
47
|
+
* @param input - Raw pasted text
|
|
48
|
+
* @param expectedState - The state value the CLI generated for this flow
|
|
49
|
+
* @returns The authorization code
|
|
50
|
+
* @throws PastedCodeError if the input is empty, is a URL without a code, or has a mismatched state
|
|
51
|
+
*/ export function parsePastedCode(input, expectedState) {
|
|
52
|
+
const parsed = parsePasteInput(input);
|
|
53
|
+
switch(parsed.kind){
|
|
54
|
+
case 'empty':
|
|
55
|
+
throw new PastedCodeError('No value provided.');
|
|
56
|
+
case 'bare-code':
|
|
57
|
+
return parsed.code;
|
|
58
|
+
case 'url-missing-code':
|
|
59
|
+
throw new PastedCodeError(NO_CODE_MESSAGE);
|
|
60
|
+
case 'url':
|
|
61
|
+
if (parsed.state !== null && parsed.state !== expectedState) {
|
|
62
|
+
throw new PastedCodeError('State mismatch — possible CSRF. Run login again.');
|
|
63
|
+
}
|
|
64
|
+
return parsed.code;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Structural validation for use as a `@clack/prompts` `text` validator.
|
|
69
|
+
*
|
|
70
|
+
* Returns `undefined` when the input could yield a code (so the prompt accepts it),
|
|
71
|
+
* or a human-readable message to re-prompt. Intentionally does NOT validate `state`
|
|
72
|
+
* — a state mismatch is a hard failure handled after the prompt resolves, not a
|
|
73
|
+
* re-prompt condition.
|
|
74
|
+
*
|
|
75
|
+
* @param input - Current prompt value
|
|
76
|
+
* @returns Error message string, or undefined if structurally valid
|
|
77
|
+
*/ export function validatePastedCode(input) {
|
|
78
|
+
const parsed = parsePasteInput(input);
|
|
79
|
+
switch(parsed.kind){
|
|
80
|
+
case 'empty':
|
|
81
|
+
return 'Paste the redirect URL or the code.';
|
|
82
|
+
case 'url-missing-code':
|
|
83
|
+
return NO_CODE_MESSAGE;
|
|
84
|
+
default:
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
}
|
package/dist/auth/pkce.d.ts
CHANGED
package/dist/auth/pkce.js
CHANGED
|
@@ -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,49 @@ 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(
|
|
47
|
-
|
|
58
|
+
export declare function refreshProjectToken(params: {
|
|
59
|
+
projectInfo?: ProjectStoreScope;
|
|
60
|
+
tenantId?: string;
|
|
61
|
+
tokenStore: TokenStore;
|
|
62
|
+
}): Promise<null | string>;
|